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