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