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