Xaction.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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"
13 #include "adaptation/icap/Config.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 "security/PeerConnector.h"
35 #include "SquidConfig.h"
36 
37 #include <optional>
38 
39 namespace Ssl
40 {
44 public:
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 
59 private:
60  /* Acl::ChecklistFiller API */
61  void fillChecklist(ACLFilledChecklist &) const override;
62 
64 };
65 } // namespace Ssl
66 
67 CBDATA_NAMESPACED_CLASS_INIT(Ssl, IcapPeerConnector);
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 
104 {
106  return nil;
107 }
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 
131 {
133 }
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.
137 namespace Ip {
138 
139 inline std::ostream &
140 operator <<(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 
151 static 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
160 void
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 
186 void
187 Adaptation::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
212  AsyncCall::Pointer callback = JobCallback(93, 3, ConnectDialer, this, Adaptation::Icap::Xaction::noteCommConnected);
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 
267 void
269 {
270  assert(Comm::IsConnOpen(conn));
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 
289 void
291 {
292  assert(!connection);
293  assert(conn);
294  assert(Comm::IsConnOpen(conn));
295  connection = conn;
296  service().noteConnectionUse(connection);
297 
299  closer = asyncCall(93, 5, "Adaptation::Icap::Xaction::noteCommClosed",
300  CloseDialer(this,&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 
372 void 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 
496 bool
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 {
606  if (IcapLogfileStatus == LOG_ENABLE) {
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 
681 bool
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 
698 void
700 {
702  if (checklist.dst_peer_name.isEmpty())
703  checklist.dst_peer_name = icapService->cfg().secure.sslDomain;
704 }
705 
706 void
708 {
709  if (error)
710  return;
711 
712  const int fd = serverConnection()->fd;
713  Security::MaybeGetSessionResumeData(fd_table[fd].ssl, icapService->sslSession);
714 }
715 
716 void
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 
void Read(const Comm::ConnectionPointer &conn, AsyncCall::Pointer &callback)
Definition: Read.cc:40
int hdr_sz
Definition: Message.h:81
const char * xstrerr(int error)
Definition: xstrerror.cc:83
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:159
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:952
bool tunneled
whether we spliced the connections instead of negotiating encryption
const XactOutcome xoError
all kinds of transaction errors
Definition: Elements.cc:21
#define Here()
source code location of the caller
Definition: Here.h:15
void commUnsetConnTimeout(const Comm::ConnectionPointer &conn)
Definition: comm.cc:616
void terminate()
Definition: MemBuf.cc:241
std::ostream & operator<<(std::ostream &os, const XactAbortInfo &xai)
Definition: Launcher.h:105
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
void noteCommConnected(const CommConnectCbParams &io)
called when the connection attempt to an ICAP service completes (successfully or not)
Definition: Xaction.cc:253
common parts of HttpRequest and HttpReply
Definition: Message.h:25
A simple PeerConnector for Secure ICAP services. No SslBump capabilities.
Definition: Xaction.cc:42
void swanSong() override
Definition: Initiate.cc:62
virtual bool initialize(Security::SessionPointer &)
CBDATA_CHILD(IcapPeerConnector)
void MaybeGetSessionResumeData(const Security::SessionPointer &, Security::SessionStatePointer &data)
Definition: Session.cc:226
virtual void fillDoneStatus(MemBuf &buf) const
Definition: Xaction.cc:667
Config TheConfig
Definition: Config.cc:19
PeerConnector(const Comm::ConnectionPointer &aServerConn, const AsyncCallback< EncryptorAnswer > &, const AccessLogEntryPointer &alp, const time_t timeout=0)
virtual void callEnd()
called right after the called job method
Definition: AsyncJob.cc:152
@ scNone
Definition: StatusCode.h:21
const XactOutcome xoUnknown
initial value: outcome was not set
Definition: Elements.cc:18
bool isEmpty() const
Definition: SBuf.h:435
CbcPointer< ErrorState > error
problem details (nil on success)
Comm::Flag ReadNow(CommIoCbParams &params, SBuf &buf)
Definition: Read.cc:81
Xaction(const char *aTypeName, ServiceRep::Pointer &aService)
Definition: Xaction.cc:69
void error(char *format,...)
@ INPROGRESS
Definition: Flag.h:21
Definition: SBuf.h:93
ServiceRep & service()
Definition: Xaction.cc:110
virtual void fillPendingStatus(MemBuf &buf) const
Definition: Xaction.cc:649
void noteInitiatorAborted() override
Definition: Xaction.cc:546
void setOutcome(const XactOutcome &xo)
Definition: Xaction.cc:560
#define LOG_ENABLE
Definition: defines.h:60
void useTransportConnection(const Comm::ConnectionPointer &)
Definition: Xaction.cc:268
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:27
@ OK
Definition: Flag.h:16
void dnsLookupDone(std::optional< Ip::Address >)
Definition: Xaction.cc:187
const Ip::Address & current() const
Definition: ipcache.h:59
void HTTPMSGUNLOCK(M *&a)
Definition: Message.h:150
static void icapLookupDnsResults(const ipcache_addrs *ia, const Dns::LookupDetails &, void *data)
Definition: Xaction.cc:152
void disableRepeats(const char *reason)
Definition: Xaction.cc:123
@ ENDFILE
Definition: Flag.h:26
A combination of PeerOptions and the corresponding Context.
Definition: PeerOptions.h:154
StatusCode
Definition: StatusCode.h:20
bool haveConnection() const
Definition: Xaction.cc:540
int xerrno
The last errno to occur. non-zero if flag is Comm::COMM_ERROR.
Definition: CommCalls.h:83
RefCount< AsyncCallT< Dialer > > asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
const XactOutcome xoGone
initiator gone, will not continue
Definition: Elements.cc:19
void noteCommClosed(const CommCloseCbParams &io)
Definition: Xaction.cc:359
void noteCommWrote(const CommIoCbParams &io)
Definition: Xaction.cc:329
time_t connect_timeout(bool bypassable) const
Definition: Config.cc:41
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
Definition: TextException.h:63
const XactOutcome xoRace
ICAP server closed pconn when we started.
Definition: Elements.cc:20
void getOutgoingAddress(HttpRequest *request, const Comm::ConnectionPointer &conn)
Definition: FwdState.cc:1481
void noteCommRead(const CommIoCbParams &io)
Definition: Xaction.cc:426
void ReadCancel(int fd, AsyncCall::Pointer &callback)
Cancel the read pending on FD. No action if none pending.
Definition: Read.cc:219
@ ICP_INVALID
Definition: icp_opcode.h:15
Comm::ConnectionPointer conn
peer connection (secured on success)
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
Definition: gadgets.cc:18
void append(const char *c, int sz) override
Definition: MemBuf.cc:209
virtual bool doneAll() const
whether positive goal has been reached
Definition: AsyncJob.cc:112
Comm::ConnectionPointer getIdleConnection(bool isRetriable)
Definition: ServiceRep.cc:118
void icapLogLog(AccessLogEntry::Pointer &al)
Definition: icap_log.cc:60
Adaptation::Icap::ServiceRep::Pointer icapService
Definition: Xaction.cc:63
void noteNegotiationDone(ErrorState *error) override
Definition: Xaction.cc:707
void start() override
called by AsyncStart; do not call directly
Definition: Xaction.cc:130
unsigned short port() const
Definition: Address.cc:798
Definition: MemBuf.h:23
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition: ipcache.cc:609
const char * status() const override
internal cleanup; do not call directly
Definition: Xaction.cc:635
Definition: Xaction.cc:39
void swanSong() override
Definition: Xaction.cc:573
Security::FuturePeerContext * peerContext() const override
Definition: Xaction.cc:57
void useIcapConnection(const Comm::ConnectionPointer &)
react to the availability of a fully-ready ICAP connection
Definition: Xaction.cc:290
virtual bool fillVirginHttpHeader(MemBuf &) const
Definition: Xaction.cc:676
#define CallJobHere(debugSection, debugLevel, job, Class, method)
Definition: AsyncJobCalls.h:59
bool doneWithIo() const
Definition: Xaction.cc:533
Comm::ConnectionPointer conn
Definition: CommCalls.h:80
void fillChecklist(ACLFilledChecklist &) const override
configure the given checklist (to reflect the current transaction state)
Definition: Xaction.cc:699
Ip::Address remote
Definition: Connection.h:149
#define assert(EX)
Definition: assert.h:17
SSL Connection
Definition: Session.h:49
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 HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:161
Comm::Flag flag
comm layer result status.
Definition: CommCalls.h:82
HttpRequest * icapRequest
sent (or at least created) ICAP request
Definition: Xaction.h:63
encapsulates DNS lookup results
Definition: LookupDetails.h:22
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
Definition: AsyncJobCalls.h:70
bool initialize(Security::SessionPointer &) override
Definition: Xaction.cc:682
const char * c_str()
Definition: SBuf.cc:516
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
Definition: Write.cc:33
int IcapLogfileStatus
Definition: icap_log.cc:20
#define asyncCallback(dbgSection, dbgLevel, method, object)
CBDATA_NAMESPACED_CLASS_INIT(Ssl, IcapPeerConnector)
const char * typeName
kid (leaf) class name, for debugging
Definition: AsyncJob.h:85
time_t io_timeout(bool bypassable) const
Definition: Config.cc:49
virtual void reset()=0
Definition: Xaction.cc:137
int ssl_ex_index_server
void callException(const std::exception &e) override
called when the job throws during an async call
Definition: Xaction.cc:372
#define fd_table
Definition: fde.h:189
bool mayReadMore() const
Definition: Xaction.cc:517
virtual void finalizeLogInfo()
Definition: Xaction.cc:612
std::shared_ptr< SSL > SessionPointer
Definition: Session.h:53
void commSetConnTimeout(const Comm::ConnectionPointer &conn, time_t timeout, AsyncCall::Pointer &callback)
Definition: comm.cc:592
const char * termedBuf() const
Definition: SquidString.h:92
const typedef char * XactOutcome
transaction result for logging
Definition: Elements.h:39
void handleSecuredPeer(Security::EncryptorAnswer &answer)
Definition: Xaction.cc:717
an std::runtime_error with thrower location info
Definition: TextException.h:20
char * content()
start of the added data
Definition: MemBuf.h:41
void fillChecklist(ACLFilledChecklist &) const override
configure the given checklist (to reflect the current transaction state)
virtual void start()
called by AsyncStart; do not call directly
Definition: AsyncJob.cc:59
#define Must(condition)
Definition: TextException.h:75
void callEnd() override
called right after the called job method
Definition: Xaction.cc:379
#define DBG_IMPORTANT
Definition: Stream.h:38
void reset()
Definition: MemBuf.cc:129
bool doneAll() const override
whether positive goal has been reached
Definition: Xaction.cc:388
void noteCommTimedout(const CommTimeoutCbParams &io)
Definition: Xaction.cc:347
bool isOpen() const
Definition: Connection.h:101
const ServiceConfig & cfg() const
Definition: Service.h:51
void scheduleWrite(MemBuf &buf)
Definition: Xaction.cc:316
virtual void callException(const std::exception &e)
called when the job throws during an async call
Definition: AsyncJob.cc:143
Network/connection security abstraction layer.
Definition: Connection.h:33
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
virtual AccessLogEntry::Pointer masterLogEntry()
Definition: Xaction.cc:103
void comm_remove_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:981
virtual bool doneReading() const
Definition: Xaction.cc:523
void setClientSNI(SSL *ssl, const char *fqdn)
Definition: support.cc:1161
void tvSub(struct timeval &res, struct timeval const &t1, struct timeval const &t2)
Definition: gadgets.cc:58
bool parseHttpMsg(Http::Message *msg)
Definition: Xaction.cc:497
ErrorDetail::Pointer MakeNamedErrorDetail(const char *name)
Definition: Detail.cc:54
virtual bool doneWriting() const
Definition: Xaction.cc:528
void SetSessionResumeData(const Security::SessionPointer &, const Security::SessionStatePointer &)
Definition: Session.cc:247
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:64
bool parse(const char *buf, const size_t sz, bool eol, Http::StatusCode *error)
Definition: Message.cc:68

 

Introduction

Documentation

Support

Miscellaneous