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