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