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