]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/icap/ModXact.h
Bug #2459 fix, access logging enhancements, ICAP logging and retries support:
[thirdparty/squid.git] / src / adaptation / icap / ModXact.h
1
2 /*
3 * $Id$
4 *
5 *
6 * SQUID Web Proxy Cache http://www.squid-cache.org/
7 * ----------------------------------------------------------
8 *
9 * Squid is the result of efforts by numerous individuals from
10 * the Internet community; see the CONTRIBUTORS file for full
11 * details. Many organizations have provided support for Squid's
12 * development; see the SPONSORS file for full details. Squid is
13 * Copyrighted (C) 2001 by the Regents of the University of
14 * California; see the COPYRIGHT file for full details. Squid
15 * incorporates software developed and/or copyrighted by other
16 * sources; see the CREDITS file for full details.
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
31 *
32 */
33
34 #ifndef SQUID_ICAPMODXACT_H
35 #define SQUID_ICAPMODXACT_H
36
37 #include "BodyPipe.h"
38 #include "adaptation/icap/Xaction.h"
39 #include "adaptation/icap/InOut.h"
40 #include "adaptation/icap/Launcher.h"
41
42 /*
43 * ICAPModXact implements ICAP REQMOD and RESPMOD transaction using
44 * ICAPXaction as the base. The ICAPModXact receives a virgin HTTP message
45 * from an ICAP vecoring point, (a.k.a., initiator), communicates with the
46 * ICAP server, and sends the adapted HTTP message headers back.
47 * Virgin/adapted HTTP message body is reveived/sent using BodyPipe
48 * interface. The initiator (or its associate) is expected to send and/or
49 * receive the HTTP body.
50 */
51
52
53 class ChunkedCodingParser;
54
55 namespace Adaptation
56 {
57 namespace Icap {
58
59 // estimated future presence and size of something (e.g., HTTP body)
60
61 class SizedEstimate
62 {
63
64 public:
65 SizedEstimate(); // not expected by default
66 void expect(int64_t aSize); // expect with any, even unknown size
67 bool expected() const;
68
69 /* other members can be accessed iff expected() */
70
71 bool knownSize() const;
72 uint64_t size() const; // can be accessed iff knownSize()
73
74 private:
75 enum { dtUnexpected = -2, dtUnknown = -1 };
76 int64_t theData; // combines expectation and size info to save RAM
77 };
78
79 // Virgin body may be used for two activities: (a) writing preview or prime
80 // body to the ICAP server and (b) sending the body back in the echo mode.
81 // Both activities use the same BodyPipe and may be active at the same time.
82 // This class is used to maintain the state of body writing or sending
83 // activity and to coordinate consumption of the shared virgin body buffer.
84 class VirginBodyAct
85 {
86
87 public:
88 VirginBodyAct();
89
90 void plan(); // the activity may happen; do not consume at or above offset
91 void disable(); // the activity wont continue; no consumption restrictions
92
93 bool active() const { return theState == stActive; }
94 bool disabled() const { return theState == stDisabled; }
95
96 // methods below require active()
97
98 uint64_t offset() const; // the absolute beginning of not-yet-acted-on data
99 void progress(size_t size); // note processed body bytes
100
101 private:
102 int64_t theStart; // unprocessed virgin body data offset
103
104 typedef enum { stUndecided, stActive, stDisabled } State;
105 State theState;
106 };
107
108
109 // maintains preview-related sizes
110
111 class Preview
112 {
113
114 public:
115 Preview(); // disabled
116 void enable(size_t anAd); // enabled with advertised size
117 bool enabled() const;
118
119 /* other members can be accessed iff enabled() */
120
121 size_t ad() const; // advertised preview size
122 size_t debt() const; // remains to write
123 bool done() const; // wrote everything
124 bool ieof() const; // premature EOF
125
126 void wrote(size_t size, bool wroteEof);
127
128 private:
129 size_t theWritten;
130 size_t theAd;
131 enum State { stDisabled, stWriting, stIeof, stDone } theState;
132 };
133
134 class ModXact: public Xaction, public BodyProducer, public BodyConsumer
135 {
136
137 public:
138 ModXact(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, ServiceRep::Pointer &s);
139
140 // BodyProducer methods
141 virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer);
142 virtual void noteBodyConsumerAborted(BodyPipe::Pointer);
143
144 // BodyConsumer methods
145 virtual void noteMoreBodyDataAvailable(BodyPipe::Pointer);
146 virtual void noteBodyProductionEnded(BodyPipe::Pointer);
147 virtual void noteBodyProducerAborted(BodyPipe::Pointer);
148
149 // comm handlers
150 virtual void handleCommConnected();
151 virtual void handleCommWrote(size_t size);
152 virtual void handleCommRead(size_t size);
153 void handleCommWroteHeaders();
154 void handleCommWroteBody();
155
156 // service waiting
157 void noteServiceReady();
158
159 public:
160 InOut virgin;
161 InOut adapted;
162
163 protected:
164 // bypasses exceptions if needed and possible
165 virtual void callException(const std::exception &e);
166
167 private:
168 virtual void start();
169
170 /// locates the request, either as a cause or as a virgin message itself
171 const HttpRequest &virginRequest() const; // Must always be available
172
173 void estimateVirginBody();
174 void makeAdaptedBodyPipe(const char *what);
175
176 void waitForService();
177
178 // will not send anything [else] on the adapted pipe
179 bool doneSending() const;
180
181 void startWriting();
182 void writeMore();
183 void writePreviewBody();
184 void writePrimeBody();
185 void writeSomeBody(const char *label, size_t size);
186
187 void startReading();
188 void readMore();
189 virtual bool doneReading() const { return commEof || state.doneParsing(); }
190 virtual bool doneWriting() const { return state.doneWriting(); }
191
192 size_t virginContentSize(const VirginBodyAct &act) const;
193 const char *virginContentData(const VirginBodyAct &act) const;
194 bool virginBodyEndReached(const VirginBodyAct &act) const;
195
196 void makeRequestHeaders(MemBuf &buf);
197 void makeUsernameHeader(const HttpRequest *request, MemBuf &buf);
198 void addLastRequestChunk(MemBuf &buf);
199 void openChunk(MemBuf &buf, size_t chunkSize, bool ieof);
200 void closeChunk(MemBuf &buf);
201 void virginConsume();
202 void finishNullOrEmptyBodyPreview(MemBuf &buf);
203
204 void decideOnPreview();
205 void decideOnRetries();
206 bool shouldAllow204();
207 bool canBackupEverything() const;
208
209 void prepBackup(size_t expectedSize);
210 void backup(const MemBuf &buf);
211
212 void parseMore();
213
214 void parseHeaders();
215 void parseIcapHead();
216 void parseHttpHead();
217 bool parseHead(HttpMsg *head);
218
219 void decideOnParsingBody();
220 void parseBody();
221 void maybeAllocateHttpMsg();
222
223 void handle100Continue();
224 bool validate200Ok();
225 void handle200Ok();
226 void handle204NoContent();
227 void handleUnknownScode();
228
229 void bypassFailure();
230
231 void startSending();
232 void disableBypass(const char *reason);
233
234 void prepEchoing();
235 void echoMore();
236
237 virtual bool doneAll() const;
238 virtual void swanSong();
239
240 void stopReceiving();
241 void stopSending(bool nicely);
242 void stopWriting(bool nicely);
243 void stopParsing();
244 void stopBackup();
245
246 virtual void fillPendingStatus(MemBuf &buf) const;
247 virtual void fillDoneStatus(MemBuf &buf) const;
248 virtual bool fillVirginHttpHeader(MemBuf&) const;
249
250 private:
251 void packHead(MemBuf &httpBuf, const HttpMsg *head);
252 void encapsulateHead(MemBuf &icapBuf, const char *section, MemBuf &httpBuf, const HttpMsg *head);
253 bool gotEncapsulated(const char *section) const;
254 void checkConsuming();
255
256 virtual void finalizeLogInfo();
257
258 SizedEstimate virginBody;
259 VirginBodyAct virginBodyWriting; // virgin body writing state
260 VirginBodyAct virginBodySending; // virgin body sending state
261 uint64_t virginConsumed; // virgin data consumed so far
262 Preview preview; // use for creating (writing) the preview
263
264 ChunkedCodingParser *bodyParser; // ICAP response body parser
265
266 bool canStartBypass; // enables bypass of transaction failures
267
268 uint64_t replyBodySize; ///< dechunked ICAP reply body size
269
270 int adaptHistoryId; ///< adaptation history slot reservation
271
272 class State
273 {
274
275 public:
276 State();
277
278 public:
279
280 bool serviceWaiting; // waiting for ICAP service options
281 bool allowedPostview204; // mmust handle 204 No Content outside preview
282
283 // will not write anything [else] to the ICAP server connection
284 bool doneWriting() const { return writing == writingReallyDone; }
285
286 // will not use virgin.body_pipe
287 bool doneConsumingVirgin() const {
288 return writing >= writingAlmostDone
289 && (sending == sendingAdapted || sending == sendingDone);
290 }
291
292 // parsed entire ICAP response from the ICAP server
293 bool doneParsing() const { return parsing == psDone; }
294
295 // is parsing ICAP or HTTP headers read from the ICAP server
296 bool parsingHeaders() const {
297 return parsing == psIcapHeader ||
298 parsing == psHttpHeader;
299 }
300
301 enum Parsing { psIcapHeader, psHttpHeader, psBody, psDone } parsing;
302
303 // measures ICAP request writing progress
304 enum Writing { writingInit, writingConnect, writingHeaders,
305 writingPreview, writingPaused, writingPrime,
306 writingAlmostDone, // waiting for the last write() call to finish
307 writingReallyDone
308 } writing;
309
310 enum Sending { sendingUndecided, sendingVirgin, sendingAdapted,
311 sendingDone
312 } sending;
313 } state;
314
315 CBDATA_CLASS2(ModXact);
316 };
317
318 // An Launcher that stores ModXact construction info and
319 // creates ModXact when needed
320 class ModXactLauncher: public Launcher
321 {
322 public:
323 ModXactLauncher(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer s);
324
325 protected:
326 virtual Xaction *createXaction();
327
328 virtual void swanSong();
329
330 /// starts or stops transaction accounting in ICAP history
331 void updateHistory(bool start);
332
333 InOut virgin;
334
335 private:
336 CBDATA_CLASS2(ModXactLauncher);
337 };
338
339
340 } // namespace Icap
341 } // namespace Adaptation
342
343 #endif /* SQUID_ICAPMOD_XACT_H */