]>
Commit | Line | Data |
---|---|---|
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 | 28 | class ChunkedCodingParser; |
29 | ||
af6a12ee AJ |
30 | namespace Adaptation |
31 | { | |
e1381638 AJ |
32 | namespace Icap |
33 | { | |
26cc52cb | 34 | |
774c051c | 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 | |
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 | |
50 | private: | |
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. | |
60 | class VirginBodyAct | |
774c051c | 61 | { |
62 | ||
63 | public: | |
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 | |
77 | private: | |
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 | 86 | class Preview |
774c051c | 87 | { |
88 | ||
89 | public: | |
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 | |
103 | private: | |
104 | size_t theWritten; | |
105 | size_t theAd; | |
106 | enum State { stDisabled, stWriting, stIeof, stDone } theState; | |
107 | }; | |
108 | ||
26cc52cb | 109 | class ModXact: public Xaction, public BodyProducer, public BodyConsumer |
774c051c | 110 | { |
111 | ||
774c051c | 112 | public: |
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 | 136 | public: |
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 | 148 | private: |
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 | |
238 | private: | |
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 | |
324 | class ModXactLauncher: public Launcher | |
c824c43b | 325 | { |
326 | public: | |
af0ded40 | 327 | ModXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp, Adaptation::ServicePointer s); |
c824c43b | 328 | |
329 | protected: | |
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 | 341 | private: |
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 */ |