]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/icap/ModXact.h
Detail the error page error
[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
60 // estimated future presence and size of something (e.g., HTTP body)
61
62 class SizedEstimate
63 {
64
65 public:
66 SizedEstimate(); // not expected by default
67 void expect(int64_t aSize); // expect with any, even unknown size
68 bool expected() const;
69
70 /* other members can be accessed iff expected() */
71
72 bool knownSize() const;
73 uint64_t size() const; // can be accessed iff knownSize()
74
75 private:
76 enum { dtUnexpected = -2, dtUnknown = -1 };
77 int64_t theData; // combines expectation and size info to save RAM
78 };
79
80 // Virgin body may be used for two activities: (a) writing preview or prime
81 // body to the ICAP server and (b) sending the body back in the echo mode.
82 // Both activities use the same BodyPipe and may be active at the same time.
83 // This class is used to maintain the state of body writing or sending
84 // activity and to coordinate consumption of the shared virgin body buffer.
85 class VirginBodyAct
86 {
87
88 public:
89 VirginBodyAct();
90
91 void plan(); // the activity may happen; do not consume at or above offset
92 void disable(); // the activity wont continue; no consumption restrictions
93
94 bool active() const { return theState == stActive; }
95 bool disabled() const { return theState == stDisabled; }
96
97 // methods below require active()
98
99 uint64_t offset() const; // the absolute beginning of not-yet-acted-on data
100 void progress(size_t size); // note processed body bytes
101
102 private:
103 int64_t theStart; // unprocessed virgin body data offset
104
105 typedef enum { stUndecided, stActive, stDisabled } State;
106 State theState;
107 };
108
109
110 // maintains preview-related sizes
111
112 class Preview
113 {
114
115 public:
116 Preview(); // disabled
117 void enable(size_t anAd); // enabled with advertised size
118 bool enabled() const;
119
120 /* other members can be accessed iff enabled() */
121
122 size_t ad() const; // advertised preview size
123 size_t debt() const; // remains to write
124 bool done() const; // wrote everything
125 bool ieof() const; // premature EOF
126
127 void wrote(size_t size, bool wroteEof);
128
129 private:
130 size_t theWritten;
131 size_t theAd;
132 enum State { stDisabled, stWriting, stIeof, stDone } theState;
133 };
134
135 class ModXact: public Xaction, public BodyProducer, public BodyConsumer
136 {
137
138 public:
139 ModXact(HttpMsg *virginHeader, HttpRequest *virginCause, ServiceRep::Pointer &s);
140 virtual ~ModXact();
141
142 // BodyProducer methods
143 virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer);
144 virtual void noteBodyConsumerAborted(BodyPipe::Pointer);
145
146 // BodyConsumer methods
147 virtual void noteMoreBodyDataAvailable(BodyPipe::Pointer);
148 virtual void noteBodyProductionEnded(BodyPipe::Pointer);
149 virtual void noteBodyProducerAborted(BodyPipe::Pointer);
150
151 // comm handlers
152 virtual void handleCommConnected();
153 virtual void handleCommWrote(size_t size);
154 virtual void handleCommRead(size_t size);
155 void handleCommWroteHeaders();
156 void handleCommWroteBody();
157
158 // service waiting
159 void noteServiceReady();
160 void noteServiceAvailable();
161
162 public:
163 InOut virgin;
164 InOut adapted;
165
166 // bypasses exceptions if needed and possible
167 virtual void callException(const std::exception &e);
168
169 /// record error detail in the virgin request if possible
170 virtual void detailError(int errDetail);
171 virtual void clearError();
172
173 private:
174 virtual void start();
175
176 /// locates the request, either as a cause or as a virgin message itself
177 const HttpRequest &virginRequest() const; // Must always be available
178
179 void estimateVirginBody();
180 void makeAdaptedBodyPipe(const char *what);
181
182 void waitForService();
183
184 // will not send anything [else] on the adapted pipe
185 bool doneSending() const;
186
187 void startWriting();
188 void writeMore();
189 void writePreviewBody();
190 void writePrimeBody();
191 void writeSomeBody(const char *label, size_t size);
192 void decideWritingAfterPreview(const char *previewKind);
193
194 void startReading();
195 void readMore();
196 virtual bool doneReading() const { return commEof || state.doneParsing(); }
197 virtual bool doneWriting() const { return state.doneWriting(); }
198
199 size_t virginContentSize(const VirginBodyAct &act) const;
200 const char *virginContentData(const VirginBodyAct &act) const;
201 bool virginBodyEndReached(const VirginBodyAct &act) const;
202
203 void makeRequestHeaders(MemBuf &buf);
204 void makeAllowHeader(MemBuf &buf);
205 void makeUsernameHeader(const HttpRequest *request, MemBuf &buf);
206 void addLastRequestChunk(MemBuf &buf);
207 void openChunk(MemBuf &buf, size_t chunkSize, bool ieof);
208 void closeChunk(MemBuf &buf);
209 void virginConsume();
210 void finishNullOrEmptyBodyPreview(MemBuf &buf);
211
212 void decideOnPreview();
213 void decideOnRetries();
214 bool shouldAllow204();
215 bool shouldAllow206any();
216 bool shouldAllow206in();
217 bool shouldAllow206out();
218 bool canBackupEverything() const;
219
220 void prepBackup(size_t expectedSize);
221 void backup(const MemBuf &buf);
222
223 void parseMore();
224
225 void parseHeaders();
226 void parseIcapHead();
227 void parseHttpHead();
228 bool parseHead(HttpMsg *head);
229
230 void decideOnParsingBody();
231 void parseBody();
232 void maybeAllocateHttpMsg();
233
234 void handle100Continue();
235 bool validate200Ok();
236 void handle200Ok();
237 void handle204NoContent();
238 void handle206PartialContent();
239 void handleUnknownScode();
240
241 void bypassFailure();
242
243 void startSending();
244 void disableBypass(const char *reason, bool includeGroupBypass);
245
246 void prepEchoing();
247 void prepPartialBodyEchoing(uint64_t pos);
248 void echoMore();
249
250 virtual bool doneAll() const;
251 virtual void swanSong();
252
253 void stopReceiving();
254 void stopSending(bool nicely);
255 void stopWriting(bool nicely);
256 void stopParsing();
257 void stopBackup();
258
259 virtual void fillPendingStatus(MemBuf &buf) const;
260 virtual void fillDoneStatus(MemBuf &buf) const;
261 virtual bool fillVirginHttpHeader(MemBuf&) const;
262
263 private:
264 void packHead(MemBuf &httpBuf, const HttpMsg *head);
265 void encapsulateHead(MemBuf &icapBuf, const char *section, MemBuf &httpBuf, const HttpMsg *head);
266 bool gotEncapsulated(const char *section) const;
267 void checkConsuming();
268
269 virtual void finalizeLogInfo();
270
271 SizedEstimate virginBody;
272 VirginBodyAct virginBodyWriting; // virgin body writing state
273 VirginBodyAct virginBodySending; // virgin body sending state
274 uint64_t virginConsumed; // virgin data consumed so far
275 Preview preview; // use for creating (writing) the preview
276
277 ChunkedCodingParser *bodyParser; // ICAP response body parser
278
279 bool canStartBypass; // enables bypass of transaction failures
280 bool protectGroupBypass; // protects ServiceGroup-wide bypass of failures
281
282 /**
283 * size of HTTP header in ICAP reply or -1 if there is not any encapsulated
284 * message data
285 */
286 int64_t replyHttpHeaderSize;
287 /**
288 * size of dechunked HTTP body in ICAP reply or -1 if there is not any
289 * encapsulated message data
290 */
291 int64_t replyHttpBodySize;
292
293 int adaptHistoryId; ///< adaptation history slot reservation
294
295 class State
296 {
297
298 public:
299 State();
300
301 public:
302
303 bool serviceWaiting; // waiting for ICAP service options
304 bool allowedPostview204; // mmust handle 204 No Content outside preview
305 bool allowedPostview206; // must handle 206 Partial Content outside preview
306 bool allowedPreview206; // must handle 206 Partial Content inside preview
307 bool readyForUob; ///< got a 206 response and expect a use-origin-body
308 bool waitedForService; ///< true if was queued at least once
309
310 // will not write anything [else] to the ICAP server connection
311 bool doneWriting() const { return writing == writingReallyDone; }
312
313 // will not use virgin.body_pipe
314 bool doneConsumingVirgin() const {
315 return writing >= writingAlmostDone
316 && ((sending == sendingAdapted && !readyForUob) ||
317 sending == sendingDone);
318 }
319
320 // parsed entire ICAP response from the ICAP server
321 bool doneParsing() const { return parsing == psDone; }
322
323 // is parsing ICAP or HTTP headers read from the ICAP server
324 bool parsingHeaders() const {
325 return parsing == psIcapHeader ||
326 parsing == psHttpHeader;
327 }
328
329 enum Parsing { psIcapHeader, psHttpHeader, psBody, psDone } parsing;
330
331 // measures ICAP request writing progress
332 enum Writing { writingInit, writingConnect, writingHeaders,
333 writingPreview, writingPaused, writingPrime,
334 writingAlmostDone, // waiting for the last write() call to finish
335 writingReallyDone
336 } writing;
337
338 enum Sending { sendingUndecided, sendingVirgin, sendingAdapted,
339 sendingDone
340 } sending;
341 } state;
342
343 CBDATA_CLASS2(ModXact);
344 };
345
346 // An Launcher that stores ModXact construction info and
347 // creates ModXact when needed
348 class ModXactLauncher: public Launcher
349 {
350 public:
351 ModXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer s);
352
353 protected:
354 virtual Xaction *createXaction();
355
356 virtual void swanSong();
357
358 /// starts or stops transaction accounting in ICAP history
359 void updateHistory(bool start);
360
361 InOut virgin;
362
363 private:
364 CBDATA_CLASS2(ModXactLauncher);
365 };
366
367
368 } // namespace Icap
369 } // namespace Adaptation
370
371 #endif /* SQUID_ICAPMOD_XACT_H */