]>
Commit | Line | Data |
---|---|---|
774c051c | 1 | |
2 | /* | |
bd7f2ede | 3 | * $Id: ICAPModXact.h,v 1.11 2008/02/12 23:12:45 rousskov Exp $ |
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" |
774c051c | 38 | #include "ICAPXaction.h" |
5f8252d2 | 39 | #include "ICAPInOut.h" |
c824c43b | 40 | #include "ICAPLauncher.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 | 52 | |
53 | class ChunkedCodingParser; | |
54 | ||
55 | // estimated future presence and size of something (e.g., HTTP body) | |
56 | ||
57 | class SizedEstimate | |
58 | { | |
59 | ||
60 | public: | |
61 | SizedEstimate(); // not expected by default | |
47f6e231 | 62 | void expect(int64_t aSize); // expect with any, even unknown size |
774c051c | 63 | bool expected() const; |
64 | ||
65 | /* other members can be accessed iff expected() */ | |
66 | ||
67 | bool knownSize() const; | |
47f6e231 | 68 | uint64_t size() const; // can be accessed iff knownSize() |
774c051c | 69 | |
70 | private: | |
71 | enum { dtUnexpected = -2, dtUnknown = -1 }; | |
47f6e231 | 72 | int64_t theData; // combines expectation and size info to save RAM |
774c051c | 73 | }; |
74 | ||
9e008dda | 75 | // Virgin body may be used for two activities: (a) writing preview or prime |
5f8252d2 | 76 | // body to the ICAP server and (b) sending the body back in the echo mode. |
77 | // Both activities use the same BodyPipe and may be active at the same time. | |
78 | // This class is used to maintain the state of body writing or sending | |
79 | // activity and to coordinate consumption of the shared virgin body buffer. | |
80 | class VirginBodyAct | |
774c051c | 81 | { |
82 | ||
83 | public: | |
478cfe99 | 84 | VirginBodyAct(); |
774c051c | 85 | |
5f8252d2 | 86 | void plan(); // the activity may happen; do not consume at or above offset |
87 | void disable(); // the activity wont continue; no consumption restrictions | |
478cfe99 | 88 | |
89 | bool active() const { return theState == stActive; } | |
90 | bool disabled() const { return theState == stDisabled; } | |
774c051c | 91 | |
92 | // methods below require active() | |
93 | ||
47f6e231 | 94 | uint64_t offset() const; // the absolute beginning of not-yet-acted-on data |
5f8252d2 | 95 | void progress(size_t size); // note processed body bytes |
774c051c | 96 | |
97 | private: | |
47f6e231 | 98 | int64_t theStart; // unprocessed virgin body data offset |
478cfe99 | 99 | |
100 | typedef enum { stUndecided, stActive, stDisabled } State; | |
101 | State theState; | |
774c051c | 102 | }; |
103 | ||
5f8252d2 | 104 | |
774c051c | 105 | // maintains preview-related sizes |
106 | ||
107 | class ICAPPreview | |
108 | { | |
109 | ||
110 | public: | |
111 | ICAPPreview(); // disabled | |
112 | void enable(size_t anAd); // enabled with advertised size | |
113 | bool enabled() const; | |
114 | ||
115 | /* other members can be accessed iff enabled() */ | |
116 | ||
117 | size_t ad() const; // advertised preview size | |
118 | size_t debt() const; // remains to write | |
119 | bool done() const; // wrote everything | |
120 | bool ieof() const; // premature EOF | |
121 | ||
c99de607 | 122 | void wrote(size_t size, bool wroteEof); |
774c051c | 123 | |
124 | private: | |
125 | size_t theWritten; | |
126 | size_t theAd; | |
127 | enum State { stDisabled, stWriting, stIeof, stDone } theState; | |
128 | }; | |
129 | ||
5f8252d2 | 130 | class ICAPModXact: public ICAPXaction, public BodyProducer, public BodyConsumer |
774c051c | 131 | { |
132 | ||
774c051c | 133 | public: |
0bef8dd7 | 134 | ICAPModXact(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, ICAPServiceRep::Pointer &s); |
774c051c | 135 | |
5f8252d2 | 136 | // BodyProducer methods |
bd7f2ede | 137 | virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer); |
138 | virtual void noteBodyConsumerAborted(BodyPipe::Pointer); | |
774c051c | 139 | |
5f8252d2 | 140 | // BodyConsumer methods |
bd7f2ede | 141 | virtual void noteMoreBodyDataAvailable(BodyPipe::Pointer); |
142 | virtual void noteBodyProductionEnded(BodyPipe::Pointer); | |
143 | virtual void noteBodyProducerAborted(BodyPipe::Pointer); | |
774c051c | 144 | |
145 | // comm handlers | |
146 | virtual void handleCommConnected(); | |
147 | virtual void handleCommWrote(size_t size); | |
148 | virtual void handleCommRead(size_t size); | |
149 | void handleCommWroteHeaders(); | |
150 | void handleCommWroteBody(); | |
151 | ||
152 | // service waiting | |
153 | void noteServiceReady(); | |
154 | ||
5f8252d2 | 155 | public: |
156 | ICAPInOut virgin; | |
157 | ICAPInOut adapted; | |
158 | ||
478cfe99 | 159 | protected: |
160 | // bypasses exceptions if needed and possible | |
0a8bbeeb | 161 | virtual void callException(const std::exception &e); |
478cfe99 | 162 | |
774c051c | 163 | private: |
5f8252d2 | 164 | virtual void start(); |
165 | ||
774c051c | 166 | void estimateVirginBody(); |
5f8252d2 | 167 | void makeAdaptedBodyPipe(const char *what); |
774c051c | 168 | |
169 | void waitForService(); | |
170 | ||
171 | // will not send anything [else] on the adapted pipe | |
172 | bool doneSending() const; | |
173 | ||
174 | void startWriting(); | |
175 | void writeMore(); | |
5f8252d2 | 176 | void writePreviewBody(); |
774c051c | 177 | void writePrimeBody(); |
178 | void writeSomeBody(const char *label, size_t size); | |
179 | ||
180 | void startReading(); | |
181 | void readMore(); | |
182 | virtual bool doneReading() const { return commEof || state.doneParsing(); } | |
c99de607 | 183 | virtual bool doneWriting() const { return state.doneWriting(); } |
774c051c | 184 | |
5f8252d2 | 185 | size_t virginContentSize(const VirginBodyAct &act) const; |
186 | const char *virginContentData(const VirginBodyAct &act) const; | |
187 | bool virginBodyEndReached(const VirginBodyAct &act) const; | |
188 | ||
774c051c | 189 | void makeRequestHeaders(MemBuf &buf); |
5f8252d2 | 190 | void makeUsernameHeader(const HttpRequest *request, MemBuf &buf); |
774c051c | 191 | void addLastRequestChunk(MemBuf &buf); |
c99de607 | 192 | void openChunk(MemBuf &buf, size_t chunkSize, bool ieof); |
193 | void closeChunk(MemBuf &buf); | |
774c051c | 194 | void virginConsume(); |
5f8252d2 | 195 | void finishNullOrEmptyBodyPreview(MemBuf &buf); |
774c051c | 196 | |
c824c43b | 197 | void decideOnPreview(); |
198 | void decideOnRetries(); | |
774c051c | 199 | bool shouldAllow204(); |
c824c43b | 200 | bool canBackupEverything() const; |
201 | ||
774c051c | 202 | void prepBackup(size_t expectedSize); |
203 | void backup(const MemBuf &buf); | |
204 | ||
205 | void parseMore(); | |
206 | ||
207 | void parseHeaders(); | |
208 | void parseIcapHead(); | |
209 | void parseHttpHead(); | |
210 | bool parseHead(HttpMsg *head); | |
211 | ||
5f8252d2 | 212 | void decideOnParsingBody(); |
774c051c | 213 | void parseBody(); |
774c051c | 214 | void maybeAllocateHttpMsg(); |
215 | ||
216 | void handle100Continue(); | |
b559db5d | 217 | bool validate200Ok(); |
774c051c | 218 | void handle200Ok(); |
219 | void handle204NoContent(); | |
220 | void handleUnknownScode(); | |
221 | ||
478cfe99 | 222 | void bypassFailure(); |
223 | ||
224 | void startSending(); | |
225 | void disableBypass(const char *reason); | |
226 | ||
227 | void prepEchoing(); | |
774c051c | 228 | void echoMore(); |
229 | ||
230 | virtual bool doneAll() const; | |
5f8252d2 | 231 | virtual void swanSong(); |
774c051c | 232 | |
774c051c | 233 | void stopReceiving(); |
234 | void stopSending(bool nicely); | |
c99de607 | 235 | void stopWriting(bool nicely); |
774c051c | 236 | void stopParsing(); |
237 | void stopBackup(); | |
238 | ||
239 | virtual void fillPendingStatus(MemBuf &buf) const; | |
240 | virtual void fillDoneStatus(MemBuf &buf) const; | |
3cfc19b3 | 241 | virtual bool fillVirginHttpHeader(MemBuf&) const; |
774c051c | 242 | |
243 | private: | |
244 | void packHead(MemBuf &httpBuf, const HttpMsg *head); | |
245 | void encapsulateHead(MemBuf &icapBuf, const char *section, MemBuf &httpBuf, const HttpMsg *head); | |
246 | bool gotEncapsulated(const char *section) const; | |
5f8252d2 | 247 | void checkConsuming(); |
774c051c | 248 | |
774c051c | 249 | |
250 | HttpReply *icapReply; | |
251 | ||
252 | SizedEstimate virginBody; | |
5f8252d2 | 253 | VirginBodyAct virginBodyWriting; // virgin body writing state |
254 | VirginBodyAct virginBodySending; // virgin body sending state | |
47f6e231 | 255 | uint64_t virginConsumed; // virgin data consumed so far |
774c051c | 256 | ICAPPreview preview; // use for creating (writing) the preview |
257 | ||
258 | ChunkedCodingParser *bodyParser; // ICAP response body parser | |
259 | ||
478cfe99 | 260 | bool canStartBypass; // enables bypass of transaction failures |
261 | ||
774c051c | 262 | class State |
263 | { | |
264 | ||
265 | public: | |
266 | State(); | |
267 | ||
268 | public: | |
269 | ||
5f8252d2 | 270 | bool serviceWaiting; // waiting for ICAP service options |
271 | bool allowedPostview204; // mmust handle 204 No Content outside preview | |
774c051c | 272 | |
273 | // will not write anything [else] to the ICAP server connection | |
c99de607 | 274 | bool doneWriting() const { return writing == writingReallyDone; } |
774c051c | 275 | |
5f8252d2 | 276 | // will not use virgin.body_pipe |
9e008dda AJ |
277 | bool doneConsumingVirgin() const { |
278 | return writing >= writingAlmostDone | |
279 | && (sending == sendingAdapted || sending == sendingDone); | |
280 | } | |
5f8252d2 | 281 | |
774c051c | 282 | // parsed entire ICAP response from the ICAP server |
283 | bool doneParsing() const { return parsing == psDone; } | |
284 | ||
285 | // is parsing ICAP or HTTP headers read from the ICAP server | |
9e008dda | 286 | bool parsingHeaders() const { |
774c051c | 287 | return parsing == psIcapHeader || |
288 | parsing == psHttpHeader; | |
289 | } | |
290 | ||
291 | enum Parsing { psIcapHeader, psHttpHeader, psBody, psDone } parsing; | |
292 | ||
293 | // measures ICAP request writing progress | |
294 | enum Writing { writingInit, writingConnect, writingHeaders, | |
9e008dda AJ |
295 | writingPreview, writingPaused, writingPrime, |
296 | writingAlmostDone, // waiting for the last write() call to finish | |
297 | writingReallyDone | |
298 | } writing; | |
774c051c | 299 | |
300 | enum Sending { sendingUndecided, sendingVirgin, sendingAdapted, | |
9e008dda AJ |
301 | sendingDone |
302 | } sending; | |
2fadd50d | 303 | } state; |
774c051c | 304 | |
305 | CBDATA_CLASS2(ICAPModXact); | |
306 | }; | |
307 | ||
9e008dda | 308 | // An ICAPLauncher that stores ICAPModXact construction info and |
c824c43b | 309 | // creates ICAPModXact when needed |
310 | class ICAPModXactLauncher: public ICAPLauncher | |
311 | { | |
312 | public: | |
0bef8dd7 | 313 | ICAPModXactLauncher(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer s); |
c824c43b | 314 | |
315 | protected: | |
316 | virtual ICAPXaction *createXaction(); | |
317 | ||
318 | ICAPInOut virgin; | |
319 | ||
320 | private: | |
321 | CBDATA_CLASS2(ICAPModXactLauncher); | |
322 | }; | |
774c051c | 323 | |
324 | #endif /* SQUID_ICAPMOD_XACT_H */ |