1 /*
2  * Copyright (C) 1996-2021 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 #ifndef SQUID_ICAPXACTION_H
10 #define SQUID_ICAPXACTION_H
11 
12 #include "AccessLogEntry.h"
13 #include "adaptation/icap/ServiceRep.h"
14 #include "adaptation/Initiate.h"
15 #include "comm/ConnOpener.h"
16 #include "HttpReply.h"
17 #include "ipcache.h"
18 #include "sbuf/SBuf.h"
19 
20 class MemBuf;
21 
22 namespace Adaptation
23 {
24 namespace Icap
25 {
26 
27 /*
28  * The ICAP Xaction implements common tasks for ICAP OPTIONS, REQMOD, and
29  * RESPMOD transactions. It is started by an Initiator. It terminates
30  * on its own, when done. Transactions communicate with Initiator using
31  * asynchronous messages because a transaction or Initiator may be gone at
32  * any time.
33  */
34 
35 // Note: Xaction must be the first parent for object-unaware cbdata to work
36 
37 class Xaction: public Adaptation::Initiate
38 {
39 
40 public:
41     Xaction(const char *aTypeName, ServiceRep::Pointer &aService);
42     virtual ~Xaction();
43 
44     void disableRetries();
45     void disableRepeats(const char *reason);
retriable()46     bool retriable() const { return isRetriable; }
repeatable()47     bool repeatable() const { return isRepeatable; }
48 
49     // comm handler wrappers, treat as private
50     void noteCommConnected(const CommConnectCbParams &io);
51     void noteCommWrote(const CommIoCbParams &io);
52     void noteCommRead(const CommIoCbParams &io);
53     void noteCommTimedout(const CommTimeoutCbParams &io);
54     void noteCommClosed(const CommCloseCbParams &io);
55 
56     // TODO: create these only when actually sending/receiving
57     HttpRequest *icapRequest; ///< sent (or at least created) ICAP request
58     HttpReply::Pointer icapReply; ///< received ICAP reply, if any
59 
60     /// the number of times we tried to get to the service, including this time
61     int attempts;
62 
63 protected:
64     virtual void start();
65     virtual void noteInitiatorAborted(); // TODO: move to Adaptation::Initiate
66 
67     // comm hanndlers; called by comm handler wrappers
68     virtual void handleCommConnected() = 0;
69     virtual void handleCommWrote(size_t sz) = 0;
70     virtual void handleCommRead(size_t sz) = 0;
71     virtual void handleCommTimedout();
72     virtual void handleCommClosed();
73 
74     void handleSecuredPeer(Security::EncryptorAnswer &answer);
75     /// record error detail if possible
detailError(int)76     virtual void detailError(int) {}
77 
78     void openConnection();
79     void closeConnection();
80     void dieOnConnectionFailure();
81     bool haveConnection() const;
82 
83     void scheduleRead();
84     void scheduleWrite(MemBuf &buf);
85     void updateTimeout();
86 
87     void cancelRead();
88 
89     bool parseHttpMsg(HttpMsg *msg); // true=success; false=needMore; throw=err
90     bool mayReadMore() const;
91 
92     virtual bool doneReading() const;
93     virtual bool doneWriting() const;
94     bool doneWithIo() const;
95     virtual bool doneAll() const;
96 
97     // called just before the 'done' transaction is deleted
98     virtual void swanSong();
99 
100     // returns a temporary string depicting transaction status, for debugging
101     virtual const char *status() const;
102     virtual void fillPendingStatus(MemBuf &buf) const;
103     virtual void fillDoneStatus(MemBuf &buf) const;
104 
105     // useful for debugging
106     virtual bool fillVirginHttpHeader(MemBuf&) const;
107 
108 public:
109     // custom exception handling and end-of-call checks
110     virtual void callException(const std::exception  &e);
111     virtual void callEnd();
112     /// clear stored error details, if any; used for retries/repeats
clearError()113     virtual void clearError() {}
114     virtual AccessLogEntry::Pointer masterLogEntry();
115     void dnsLookupDone(const ipcache_addrs *ia);
116 
117 protected:
118     // logging
119     void setOutcome(const XactOutcome &xo);
120     virtual void finalizeLogInfo();
121 
122 public:
123     ServiceRep &service();
124 
125 private:
126     void tellQueryAborted();
127     void maybeLog();
128 
129 protected:
130     Comm::ConnectionPointer connection;     ///< ICAP server connection
131     Adaptation::Icap::ServiceRep::Pointer theService;
132 
133     SBuf readBuf;
134     bool commEof;
135     bool reuseConnection;
136     bool isRetriable;  ///< can retry on persistent connection failures
137     bool isRepeatable; ///< can repeat if no or unsatisfactory response
138     bool ignoreLastWrite;
139 
140     const char *stopReason;
141 
142     // active (pending) comm callbacks for the ICAP server connection
143     AsyncCall::Pointer connector;
144     AsyncCall::Pointer reader;
145     AsyncCall::Pointer writer;
146     AsyncCall::Pointer closer;
147 
148     AccessLogEntry::Pointer alep; ///< icap.log entry
149     AccessLogEntry &al; ///< short for *alep
150 
151     timeval icap_tr_start;     /*time when the ICAP transaction was created */
152     timeval icap_tio_start;    /*time when the first ICAP request byte was scheduled for sending*/
153     timeval icap_tio_finish;   /*time when the last byte of the ICAP responsewas received*/
154 
155 private:
156     Comm::ConnOpener::Pointer cs;
157     AsyncCall::Pointer securer; ///< whether we are securing a connection
158 };
159 
160 } // namespace Icap
161 } // namespace Adaptation
162 
163 #endif /* SQUID_ICAPXACTION_H */
164 
165