Squid Web Cache master
Loading...
Searching...
No Matches
Xaction.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 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/* DEBUG: section 93 ICAP (RFC 3507) Client */
10
11#include "squid.h"
12#include "acl/FilledChecklist.h"
16#include "base/AsyncCallbacks.h"
17#include "base/IoManip.h"
18#include "base/JobWait.h"
19#include "base/TextException.h"
20#include "comm.h"
21#include "comm/Connection.h"
22#include "comm/ConnOpener.h"
23#include "comm/Read.h"
24#include "comm/Write.h"
25#include "CommCalls.h"
26#include "error/Detail.h"
27#include "fde.h"
28#include "FwdState.h"
29#include "globals.h"
30#include "HttpReply.h"
31#include "icap_log.h"
32#include "ipcache.h"
33#include "pconn.h"
35#include "SquidConfig.h"
36
37#include <optional>
38
39namespace Ssl
40{
44public:
47 const Comm::ConnectionPointer &aServerConn,
49 AccessLogEntry::Pointer const &alp,
50 const time_t timeout = 0):
51 AsyncJob("Ssl::IcapPeerConnector"),
52 Security::PeerConnector(aServerConn, aCallback, alp, timeout), icapService(service) {}
53
54 /* Security::PeerConnector API */
55 bool initialize(Security::SessionPointer &) override;
56 void noteNegotiationDone(ErrorState *error) override;
57 Security::FuturePeerContext *peerContext() const override { return &icapService->tlsContext; }
58
59private:
60 /* Acl::ChecklistFiller API */
61 void fillChecklist(ACLFilledChecklist &) const override;
62
64};
65} // namespace Ssl
66
68
70 AsyncJob(aTypeName),
71 Adaptation::Initiate(aTypeName),
72 icapRequest(nullptr),
73 icapReply(nullptr),
74 attempts(0),
75 theService(aService),
76 commEof(false),
77 reuseConnection(true),
78 isRetriable(true),
79 isRepeatable(true),
80 ignoreLastWrite(false),
81 waitingForDns(false),
82 alep(new AccessLogEntry),
83 al(*alep)
84{
85 debugs(93,3, typeName << " constructed, this=" << this <<
86 " [icapx" << id << ']'); // we should not call virtual status() here
87 const auto mx = MasterXaction::MakePortless<XactionInitiator::initAdaptation>();
88 icapRequest = new HttpRequest(mx);
91 memset(&icap_tio_start, 0, sizeof(icap_tio_start));
92 memset(&icap_tio_finish, 0, sizeof(icap_tio_finish));
93}
94
96{
97 debugs(93,3, typeName << " destructed, this=" << this <<
98 " [icapx" << id << ']'); // we should not call virtual status() here
99 HTTPMSGUNLOCK(icapRequest);
100}
101
108
111{
112 Must(theService != nullptr);
113 return *theService;
114}
115
117{
118 debugs(93,5, typeName << (isRetriable ? " from now on" : " still") <<
119 " cannot be retried " << status());
120 isRetriable = false;
121}
122
124{
125 debugs(93,5, typeName << (isRepeatable ? " from now on" : " still") <<
126 " cannot be repeated because " << reason << status());
127 isRepeatable = false;
128}
129
134
135// TODO: Make reusable by moving this (and the printing operator from
136// ip/Address.h that this code is calling) into ip/print.h or similar.
137namespace Ip {
138
139inline std::ostream &
140operator <<(std::ostream &os, const std::optional<Address> &optional)
141{
142 if (optional.has_value())
143 os << optional.value();
144 else
145 os << "[no IP]";
146 return os;
147}
148
149}
150
151static void
153{
154 Adaptation::Icap::Xaction *xa = static_cast<Adaptation::Icap::Xaction *>(data);
155 const auto &addr = ia ? std::optional<Ip::Address>(ia->current()) : std::optional<Ip::Address>();
157}
158
159// TODO: obey service-specific, OPTIONS-reported connection limit
160void
162{
163 Must(!haveConnection());
164
165 Adaptation::Icap::ServiceRep &s = service();
166
168 disableRetries(); // this will also safely drain pconn pool
169
170 if (const auto pconn = s.getIdleConnection(isRetriable)) {
171 useTransportConnection(pconn);
172 return;
173 }
174
175 disableRetries(); // we only retry pconn failures
176
177 // Attempt to open a new connection...
178 debugs(93,3, typeName << " opens connection to " << s.cfg().host.termedBuf() << ":" << s.cfg().port);
179
180 // Locate the Service IP(s) to open
181 assert(!waitingForDns);
182 waitingForDns = true; // before the possibly-synchronous ipcache_nbgethostbyname()
184}
185
186void
187Adaptation::Icap::Xaction::dnsLookupDone(std::optional<Ip::Address> addr)
188{
189 assert(waitingForDns);
190 waitingForDns = false;
191
192 Adaptation::Icap::ServiceRep &s = service();
193
194 if (!addr.has_value()) {
195 debugs(44, DBG_IMPORTANT, "ERROR: ICAP: Unknown service host: " << s.cfg().host);
196
197#if WHEN_IPCACHE_NBGETHOSTBYNAME_USES_ASYNC_CALLS
198 dieOnConnectionFailure(); // throws
199#else // take a step back into protected Async call dialing.
201#endif
202 return;
203 }
204
205 const Comm::ConnectionPointer conn = new Comm::Connection();
206 conn->remote = addr.value();
207 conn->remote.port(s.cfg().port);
208 getOutgoingAddress(nullptr, conn);
209
210 // TODO: service bypass status may differ from that of a transaction
213 const auto cs = new Comm::ConnOpener(conn, callback, TheConfig.connect_timeout(service().cfg().bypass));
214 cs->setHost(s.cfg().host.termedBuf());
215 transportWait.start(cs, callback);
216}
217
219{
220 if (haveConnection()) {
221
222 if (closer != nullptr) {
223 comm_remove_close_handler(connection->fd, closer);
224 closer = nullptr;
225 }
226
227 commUnsetConnTimeout(connection);
228
229 cancelRead(); // may not work
230
231 if (reuseConnection && !doneWithIo()) {
232 //status() adds leading spaces.
233 debugs(93,5, "not reusing pconn due to pending I/O" << status());
234 reuseConnection = false;
235 }
236
237 if (reuseConnection)
238 disableRetries();
239
240 const bool reset = !reuseConnection &&
241 (al.icap.outcome == xoGone || al.icap.outcome == xoError);
242
243 Adaptation::Icap::ServiceRep &s = service();
244 s.putConnection(connection, reuseConnection, reset, status());
245
246 writer = nullptr;
247 reader = nullptr;
248 connection = nullptr;
249 }
250}
251
254{
255 transportWait.finish();
256
257 if (io.flag != Comm::OK) {
258 dieOnConnectionFailure(); // throws
259 return;
260 }
261
262 useTransportConnection(io.conn);
263}
264
267void
269{
271 assert(!connection);
272
273 // If it is a reused connection and the TLS object is built
274 // we should not negotiate new TLS session
275 const auto &ssl = fd_table[conn->fd].ssl;
276 if (!ssl && service().cfg().secure.encryptTransport) {
277 // XXX: Exceptions orphan conn.
278 const auto callback = asyncCallback(93, 4, Adaptation::Icap::Xaction::handleSecuredPeer, this);
279 const auto sslConnector = new Ssl::IcapPeerConnector(theService, conn, callback, masterLogEntry(), TheConfig.connect_timeout(service().cfg().bypass));
280
281 encryptionWait.start(sslConnector, callback);
282 return;
283 }
284
285 useIcapConnection(conn);
286}
287
289void
291{
292 assert(!connection);
293 assert(conn);
295 connection = conn;
296 service().noteConnectionUse(connection);
297
299 closer = asyncCall(93, 5, "Adaptation::Icap::Xaction::noteCommClosed",
301 comm_add_close_handler(connection->fd, closer);
302
303 startShoveling();
304}
305
307{
308 debugs(93, 2, typeName <<
309 " failed to connect to " << service().cfg().uri);
310 service().noteConnectionFailed("failure");
311 static const auto d = MakeNamedErrorDetail("ICAP_XACT_START");
312 detailError(d);
313 throw TexcHere("cannot connect to the ICAP service");
314}
315
317{
318 Must(haveConnection());
319
320 // comm module will free the buffer
322 writer = JobCallback(93, 3,
324
325 Comm::Write(connection, &buf, writer);
326 updateTimeout();
327}
328
330{
331 Must(writer != nullptr);
332 writer = nullptr;
333
334 if (ignoreLastWrite) {
335 // a hack due to comm inability to cancel a pending write
336 ignoreLastWrite = false;
337 debugs(93, 7, "ignoring last write; status: " << io.flag);
338 } else {
339 Must(io.flag == Comm::OK);
340 al.icap.bytesSent += io.size;
341 updateTimeout();
342 handleCommWrote(io.size);
343 }
344}
345
346// communication timeout with the ICAP service
348{
349 debugs(93, 2, typeName << " failed: timeout with " <<
350 theService->cfg().methodStr() << " " <<
351 theService->cfg().uri << status());
352 reuseConnection = false;
353 assert(haveConnection());
354 closeConnection();
355 throw TextException("timed out while talking to the ICAP service", Here());
356}
357
358// unexpected connection close while talking to the ICAP service
360{
361 if (connection) {
362 connection->noteClosure();
363 connection = nullptr;
364 }
365 closer = nullptr;
366
367 static const auto d = MakeNamedErrorDetail("ICAP_XACT_CLOSE");
368 detailError(d);
369 mustStop("ICAP service connection externally closed");
370}
371
372void Adaptation::Icap::Xaction::callException(const std::exception &e)
373{
374 setOutcome(xoError);
375 service().noteFailure();
377}
378
380{
381 if (doneWithIo()) {
382 debugs(93, 5, typeName << " done with I/O" << status());
383 closeConnection();
384 }
385 Adaptation::Initiate::callEnd(); // may destroy us
386}
387
389{
390 return !waitingForDns && !transportWait && !encryptionWait &&
391 !reader && !writer &&
393}
394
396{
397 Must(haveConnection());
398
399 if (reader != nullptr || writer != nullptr) {
400 // restart the timeout before each I/O
401 // XXX: why does Config.Timeout lacks a write timeout?
402 // TODO: service bypass status may differ from that of a transaction
405 commSetConnTimeout(connection, TheConfig.io_timeout(service().cfg().bypass), call);
406 } else {
407 // clear timeout when there is no I/O
408 // Do we need a lifetime timeout?
409 commUnsetConnTimeout(connection);
410 }
411}
412
414{
415 Must(haveConnection());
416 Must(!reader);
417 Must(readBuf.length() < SQUID_TCP_SO_RCVBUF); // will expand later if needed
418
420 reader = JobCallback(93, 3, Dialer, this, Adaptation::Icap::Xaction::noteCommRead);
421 Comm::Read(connection, reader);
422 updateTimeout();
423}
424
425// comm module read a portion of the ICAP response for us
427{
428 Must(reader != nullptr);
429 reader = nullptr;
430
431 Must(io.flag == Comm::OK);
432
433 // TODO: tune this better to expected message sizes
434 readBuf.reserveCapacity(SQUID_TCP_SO_RCVBUF);
435 // we are not asked to grow beyond the allowed maximum
436 Must(readBuf.length() < SQUID_TCP_SO_RCVBUF);
437 // now we can ensure that there is space to read new data,
438 // even if readBuf.spaceSize() currently returns zero.
439 readBuf.rawAppendStart(1);
440
441 CommIoCbParams rd(this); // will be expanded with ReadNow results
442 rd.conn = io.conn;
443 rd.size = SQUID_TCP_SO_RCVBUF - readBuf.length();
444
445 switch (Comm::ReadNow(rd, readBuf)) {
446 case Comm::INPROGRESS:
447 if (readBuf.isEmpty())
448 debugs(33, 2, io.conn << ": no data to process, " << xstrerr(rd.xerrno));
449 scheduleRead();
450 return;
451
452 case Comm::OK:
453 al.icap.bytesRead += rd.size;
454
455 updateTimeout();
456
457 debugs(93, 3, "read " << rd.size << " bytes");
458
459 disableRetries(); // because pconn did not fail
460
461 /* Continue to process previously read data */
462 break;
463
464 case Comm::ENDFILE: // close detected by 0-byte read
465 commEof = true;
466 reuseConnection = false;
467
468 // detect a pconn race condition: eof on the first pconn read
469 if (!al.icap.bytesRead && retriable()) {
470 setOutcome(xoRace);
471 mustStop("pconn race");
472 return;
473 }
474
475 break;
476
477 // case Comm::COMM_ERROR:
478 default: // no other flags should ever occur
479 debugs(11, 2, io.conn << ": read failure: " << xstrerr(rd.xerrno));
480 mustStop("unknown ICAP I/O read error");
481 return;
482 }
483
484 handleCommRead(io.size);
485}
486
488{
489 if (reader != nullptr) {
490 Must(haveConnection());
491 Comm::ReadCancel(connection->fd, reader);
492 reader = nullptr;
493 }
494}
495
496bool
498{
499 debugs(93, 5, "have " << readBuf.length() << " head bytes to parse");
500
502 // XXX: performance regression c_str() data copies
503 const char *buf = readBuf.c_str();
504 const bool parsed = msg->parse(buf, readBuf.length(), commEof, &error);
505 Must(parsed || !error); // success or need more data
506
507 if (!parsed) { // need more data
508 Must(mayReadMore());
509 msg->reset();
510 return false;
511 }
512
513 readBuf.consume(msg->hdr_sz);
514 return true;
515}
516
518{
519 return !doneReading() && // will read more data
520 readBuf.length() < SQUID_TCP_SO_RCVBUF; // have space for more data
521}
522
524{
525 return commEof;
526}
527
529{
530 return !writer;
531}
532
534{
535 return haveConnection() &&
536 !transportWait && !reader && !writer && // fast checks, some redundant
537 doneReading() && doneWriting();
538}
539
541{
542 return connection != nullptr && connection->isOpen();
543}
544
545// initiator aborted
547{
548
549 if (theInitiator.set()) {
550 debugs(93,4, "Initiator gone before ICAP transaction ended");
551 clearInitiator();
552 static const auto d = MakeNamedErrorDetail("ICAP_INIT_GONE");
553 detailError(d);
554 setOutcome(xoGone);
555 mustStop("initiator aborted");
556 }
557
558}
559
561{
562 if (al.icap.outcome != xoUnknown) {
563 debugs(93, 3, "WARNING: resetting outcome: from " << al.icap.outcome << " to " << xo);
564 } else {
565 debugs(93, 4, xo);
566 }
567 al.icap.outcome = xo;
568}
569
570// This 'last chance' method is called before a 'done' transaction is deleted.
571// It is wrong to call virtual methods from a destructor. Besides, this call
572// indicates that the transaction will terminate as planned.
574{
575 // kids should sing first and then call the parent method.
576 if (transportWait || encryptionWait) {
577 service().noteConnectionFailed("abort");
578 }
579
580 closeConnection(); // TODO: rename because we do not always close
581
582 readBuf.clear();
583
584 tellQueryAborted();
585
586 maybeLog();
587
589}
590
592{
593 if (theInitiator.set()) {
594 Adaptation::Icap::XactAbortInfo abortInfo(icapRequest, icapReply.getRaw(),
595 retriable(), repeatable());
596 Launcher *launcher = dynamic_cast<Launcher*>(theInitiator.get());
597 // launcher may be nil if initiator is invalid
598 CallJobHere1(91,5, CbcPointer<Launcher>(launcher),
599 Launcher, noteXactAbort, abortInfo);
600 clearInitiator();
601 }
602}
603
605{
607 finalizeLogInfo();
608 icapLogLog(alep);
609 }
610}
611
613{
614 //prepare log data
615 al.icp.opcode = ICP_INVALID;
616
617 const Adaptation::Icap::ServiceRep &s = service();
618 al.icap.hostAddr = s.cfg().host.termedBuf();
619 al.icap.serviceName = s.cfg().key;
620 al.icap.reqUri = s.cfg().uri;
621
622 tvSub(al.icap.ioTime, icap_tio_start, icap_tio_finish);
623 tvSub(al.icap.trTime, icap_tr_start, current_time);
624
625 al.icap.request = icapRequest;
626 HTTPMSGLOCK(al.icap.request);
627 if (icapReply != nullptr) {
628 al.icap.reply = icapReply.getRaw();
629 HTTPMSGLOCK(al.icap.reply);
630 al.icap.resStatus = icapReply->sline.status();
631 }
632}
633
634// returns a temporary string depicting transaction status, for debugging
636{
637 static MemBuf buf;
638 buf.reset();
639 buf.append(" [", 2);
640 fillPendingStatus(buf);
641 buf.append("/", 1);
642 fillDoneStatus(buf);
643 buf.appendf(" %s%u]", id.prefix(), id.value);
644 buf.terminate();
645
646 return buf.content();
647}
648
650{
651 if (haveConnection()) {
652 buf.appendf("FD %d", connection->fd);
653
654 if (writer != nullptr)
655 buf.append("w", 1);
656
657 if (reader != nullptr)
658 buf.append("r", 1);
659
660 buf.append(";", 1);
661 }
662
663 if (waitingForDns)
664 buf.append("D", 1);
665}
666
668{
669 if (haveConnection() && commEof)
670 buf.appendf("Comm(%d)", connection->fd);
671
672 if (stopReason != nullptr)
673 buf.append("Stopped", 7);
674}
675
677{
678 return false;
679}
680
681bool
683{
684 if (!Security::PeerConnector::initialize(serverSession))
685 return false;
686
687 assert(!icapService->cfg().secure.sslDomain.isEmpty());
688#if USE_OPENSSL
689 SBuf *host = new SBuf(icapService->cfg().secure.sslDomain);
690 SSL_set_ex_data(serverSession.get(), ssl_ex_index_server, host);
691 setClientSNI(serverSession.get(), host->c_str());
692#endif
693
694 Security::SetSessionResumeData(serverSession, icapService->sslSession);
695 return true;
696}
697
698void
700{
702 if (checklist.dst_peer_name.isEmpty())
703 checklist.dst_peer_name = icapService->cfg().secure.sslDomain;
704}
705
706void
708{
709 if (error)
710 return;
711
712 const int fd = serverConnection()->fd;
713 Security::MaybeGetSessionResumeData(fd_table[fd].ssl, icapService->sslSession);
714}
715
716void
718{
719 encryptionWait.finish();
720
721 assert(!answer.tunneled);
722 if (answer.error.get()) {
723 assert(!answer.conn);
724 // TODO: Refactor dieOnConnectionFailure() to be usable here as well.
725 debugs(93, 2, typeName <<
726 " TLS negotiation to " << service().cfg().uri << " failed");
727 service().noteConnectionFailed("failure");
728 static const auto d = MakeNamedErrorDetail("ICAP_XACT_SSL_START");
729 detailError(d);
730 throw TexcHere("cannot connect to the TLS ICAP service");
731 }
732
733 debugs(93, 5, "TLS negotiation to " << service().cfg().uri << " complete");
734
735 assert(answer.conn);
736
737 // The socket could get closed while our callback was queued. Sync
738 // Connection. XXX: Connection::fd may already be stale/invalid here.
739 if (answer.conn->isOpen() && fd_table[answer.conn->fd].closing()) {
740 answer.conn->noteClosure();
741 service().noteConnectionFailed("external TLS connection closure");
742 static const auto d = MakeNamedErrorDetail("ICAP_XACT_SSL_CLOSE");
743 detailError(d);
744 throw TexcHere("external closure of the TLS ICAP service connection");
745 }
746
747 useIcapConnection(answer.conn);
748}
749
RefCount< AsyncCallT< Dialer > > asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition AsyncCall.h:156
#define asyncCallback(dbgSection, dbgLevel, method, object)
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
#define CallJobHere(debugSection, debugLevel, job, Class, method)
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
ErrorDetail::Pointer MakeNamedErrorDetail(const char *name)
Definition Detail.cc:54
void getOutgoingAddress(HttpRequest *request, const Comm::ConnectionPointer &conn)
Definition FwdState.cc:1481
#define Here()
source code location of the caller
Definition Here.h:15
static std::ostream & operator<<(std::ostream &os, const acl_httpstatus_data *status)
reports acl_httpstatus_data using squid.conf http_status ACL value format
Definition HttpStatus.cc:67
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
#define Must(condition)
static void icapLookupDnsResults(const ipcache_addrs *ia, const Dns::LookupDetails &, void *data)
Definition Xaction.cc:152
void error(char *format,...)
#define assert(EX)
Definition assert.h:17
#define SQUID_TCP_SO_RCVBUF
Definition autoconf.h:1458
#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type)
Definition cbdata.h:333
time_t io_timeout(bool bypassable) const
Definition Config.cc:49
time_t connect_timeout(bool bypassable) const
Definition Config.cc:41
Comm::ConnectionPointer getIdleConnection(bool isRetriable)
void handleSecuredPeer(Security::EncryptorAnswer &answer)
Definition Xaction.cc:717
void noteCommConnected(const CommConnectCbParams &io)
called when the connection attempt to an ICAP service completes (successfully or not)
Definition Xaction.cc:253
void start() override
called by AsyncStart; do not call directly
Definition Xaction.cc:130
void noteCommWrote(const CommIoCbParams &io)
Definition Xaction.cc:329
void callException(const std::exception &e) override
called when the job throws during an async call
Definition Xaction.cc:372
bool haveConnection() const
Definition Xaction.cc:540
virtual bool fillVirginHttpHeader(MemBuf &) const
Definition Xaction.cc:676
bool mayReadMore() const
Definition Xaction.cc:517
HttpRequest * icapRequest
sent (or at least created) ICAP request
Definition Xaction.h:63
bool parseHttpMsg(Http::Message *msg)
Definition Xaction.cc:497
void useTransportConnection(const Comm::ConnectionPointer &)
Definition Xaction.cc:268
void useIcapConnection(const Comm::ConnectionPointer &)
react to the availability of a fully-ready ICAP connection
Definition Xaction.cc:290
void noteCommClosed(const CommCloseCbParams &io)
Definition Xaction.cc:359
virtual AccessLogEntry::Pointer masterLogEntry()
Definition Xaction.cc:103
virtual bool doneReading() const
Definition Xaction.cc:523
bool doneAll() const override
whether positive goal has been reached
Definition Xaction.cc:388
virtual bool doneWriting() const
Definition Xaction.cc:528
void swanSong() override
Definition Xaction.cc:573
bool doneWithIo() const
Definition Xaction.cc:533
ServiceRep & service()
Definition Xaction.cc:110
Xaction(const char *aTypeName, ServiceRep::Pointer &aService)
Definition Xaction.cc:69
virtual void fillDoneStatus(MemBuf &buf) const
Definition Xaction.cc:667
void disableRepeats(const char *reason)
Definition Xaction.cc:123
void dnsLookupDone(std::optional< Ip::Address >)
Definition Xaction.cc:187
const char * status() const override
internal cleanup; do not call directly
Definition Xaction.cc:635
void noteCommRead(const CommIoCbParams &io)
Definition Xaction.cc:426
void noteInitiatorAborted() override
Definition Xaction.cc:546
void scheduleWrite(MemBuf &buf)
Definition Xaction.cc:316
virtual void fillPendingStatus(MemBuf &buf) const
Definition Xaction.cc:649
void callEnd() override
called right after the called job method
Definition Xaction.cc:379
void setOutcome(const XactOutcome &xo)
Definition Xaction.cc:560
void noteCommTimedout(const CommTimeoutCbParams &io)
Definition Xaction.cc:347
virtual void finalizeLogInfo()
Definition Xaction.cc:612
void swanSong() override
Definition Initiate.cc:62
const ServiceConfig & cfg() const
Definition Service.h:51
a smart AsyncCall pointer for delivery of future results
virtual bool doneAll() const
whether positive goal has been reached
Definition AsyncJob.cc:112
virtual void start()
called by AsyncStart; do not call directly
Definition AsyncJob.cc:59
virtual void callEnd()
called right after the called job method
Definition AsyncJob.cc:152
const char * typeName
kid (leaf) class name, for debugging
Definition AsyncJob.h:85
virtual void callException(const std::exception &e)
called when the job throws during an async call
Definition AsyncJob.cc:143
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition CbcPointer.h:159
int xerrno
The last errno to occur. non-zero if flag is Comm::COMM_ERROR.
Definition CommCalls.h:83
Comm::Flag flag
comm layer result status.
Definition CommCalls.h:82
Comm::ConnectionPointer conn
Definition CommCalls.h:80
bool isOpen() const
Definition Connection.h:101
Ip::Address remote
Definition Connection.h:152
const Ip::Address & current() const
Definition ipcache.h:59
encapsulates DNS lookup results
common parts of HttpRequest and HttpReply
Definition Message.h:26
virtual void reset()=0
bool parse(const char *buf, const size_t sz, bool eol, Http::StatusCode *error)
Definition Message.cc:68
unsigned short port() const
Definition Address.cc:790
void append(const char *c, int sz) override
Definition MemBuf.cc:209
char * content()
start of the added data
Definition MemBuf.h:41
void reset()
Definition MemBuf.cc:129
void terminate()
Definition MemBuf.cc:241
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition Packable.h:61
Definition SBuf.h:94
const char * c_str()
Definition SBuf.cc:516
bool isEmpty() const
Definition SBuf.h:435
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
A combination of PeerOptions and the corresponding Context.
virtual bool initialize(Security::SessionPointer &)
PeerConnector(const Comm::ConnectionPointer &aServerConn, const AsyncCallback< EncryptorAnswer > &, const AccessLogEntryPointer &alp, const time_t timeout=0)
void fillChecklist(ACLFilledChecklist &) const override
configure the given checklist (to reflect the current transaction state)
A simple PeerConnector for Secure ICAP services. No SslBump capabilities.
Definition Xaction.cc:42
Adaptation::Icap::ServiceRep::Pointer icapService
Definition Xaction.cc:63
IcapPeerConnector(Adaptation::Icap::ServiceRep::Pointer &service, const Comm::ConnectionPointer &aServerConn, const AsyncCallback< Security::EncryptorAnswer > &aCallback, AccessLogEntry::Pointer const &alp, const time_t timeout=0)
Definition Xaction.cc:45
void fillChecklist(ACLFilledChecklist &) const override
configure the given checklist (to reflect the current transaction state)
Definition Xaction.cc:699
CBDATA_CHILD(IcapPeerConnector)
bool initialize(Security::SessionPointer &) override
Definition Xaction.cc:682
Security::FuturePeerContext * peerContext() const override
Definition Xaction.cc:57
void noteNegotiationDone(ErrorState *error) override
Definition Xaction.cc:707
char const * termedBuf() const
Definition SquidString.h:93
an std::runtime_error with thrower location info
void commUnsetConnTimeout(const Comm::ConnectionPointer &conn)
Definition comm.cc:618
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
Definition comm.cc:942
void comm_remove_close_handler(int fd, CLCB *handler, void *data)
Definition comm.cc:971
void commSetConnTimeout(const Comm::ConnectionPointer &conn, time_t timeout, AsyncCall::Pointer &callback)
Definition comm.cc:594
#define DBG_IMPORTANT
Definition Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition Stream.h:192
#define LOG_ENABLE
Definition defines.h:60
#define fd_table
Definition fde.h:189
int ssl_ex_index_server
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition ipcache.cc:609
@ ICP_INVALID
Definition icp_opcode.h:15
void setClientSNI(SSL *ssl, const char *fqdn)
Definition support.cc:1166
void HTTPMSGUNLOCK(M *&a)
Definition Message.h:150
void HTTPMSGLOCK(Http::Message *a)
Definition Message.h:161
void icapLogLog(AccessLogEntry::Pointer &al)
Definition icap_log.cc:60
int IcapLogfileStatus
Definition icap_log.cc:20
const XactOutcome xoGone
initiator gone, will not continue
Definition Elements.cc:19
const XactOutcome xoRace
ICAP server closed pconn when we started.
Definition Elements.cc:20
const XactOutcome xoError
all kinds of transaction errors
Definition Elements.cc:21
Config TheConfig
Definition Config.cc:19
const char * XactOutcome
transaction result for logging
Definition Elements.h:39
const XactOutcome xoUnknown
initial value: outcome was not set
Definition Elements.cc:18
void ReadCancel(int fd, AsyncCall::Pointer &callback)
Cancel the read pending on FD. No action if none pending.
Definition Read.cc:219
void Read(const Comm::ConnectionPointer &conn, AsyncCall::Pointer &callback)
Definition Read.cc:40
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition Connection.cc:27
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
Definition Write.cc:33
@ OK
Definition Flag.h:16
@ ENDFILE
Definition Flag.h:26
@ INPROGRESS
Definition Flag.h:21
Comm::Flag ReadNow(CommIoCbParams &params, SBuf &buf)
Definition Read.cc:81
StatusCode
Definition StatusCode.h:20
@ scNone
Definition StatusCode.h:21
Definition Xaction.cc:137
Network/connection security abstraction layer.
Definition Connection.h:34
void SetSessionResumeData(const Security::SessionPointer &, const Security::SessionStatePointer &)
Definition Session.cc:280
std::shared_ptr< SSL > SessionPointer
Definition Session.h:53
void MaybeGetSessionResumeData(const Security::SessionPointer &, Security::SessionStatePointer &data)
Definition Session.cc:259
Definition Xaction.cc:40
void tvSub(struct timeval &res, struct timeval const &t1, struct timeval const &t2)
Definition gadgets.cc:58
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
Definition gadgets.cc:18
const char * xstrerr(int error)
Definition xstrerror.cc:83