]>
Commit | Line | Data |
---|---|---|
774c051c | 1 | |
2 | /* | |
478cfe99 | 3 | * $Id: ICAPModXact.h,v 1.9 2007/06/19 21:12:15 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. | |
22 | * | |
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. | |
27 | * | |
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 | |
62 | void expect(ssize_t aSize); // expect with any, even unknown size | |
63 | bool expected() const; | |
64 | ||
65 | /* other members can be accessed iff expected() */ | |
66 | ||
67 | bool knownSize() const; | |
68 | size_t size() const; // can be accessed iff knownSize() | |
69 | ||
70 | private: | |
71 | enum { dtUnexpected = -2, dtUnknown = -1 }; | |
72 | ssize_t theData; // combines expectation and size info to save RAM | |
73 | }; | |
74 | ||
5f8252d2 | 75 | // Virgin body may be used for two activities: (a) writing preview or prime |
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 | ||
5f8252d2 | 94 | size_t offset() const; // the absolute beginning of not-yet-acted-on data |
95 | void progress(size_t size); // note processed body bytes | |
774c051c | 96 | |
97 | private: | |
478cfe99 | 98 | size_t theStart; // unprocessed virgin body data offset |
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 ICAPInitiator; |
131 | ||
132 | class ICAPModXact: public ICAPXaction, public BodyProducer, public BodyConsumer | |
774c051c | 133 | { |
134 | ||
774c051c | 135 | public: |
5f8252d2 | 136 | ICAPModXact(ICAPInitiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, ICAPServiceRep::Pointer &s); |
774c051c | 137 | |
5f8252d2 | 138 | // BodyProducer methods |
139 | virtual void noteMoreBodySpaceAvailable(BodyPipe &); | |
140 | virtual void noteBodyConsumerAborted(BodyPipe &); | |
774c051c | 141 | |
5f8252d2 | 142 | // BodyConsumer methods |
143 | virtual void noteMoreBodyDataAvailable(BodyPipe &); | |
144 | virtual void noteBodyProductionEnded(BodyPipe &); | |
145 | virtual void noteBodyProducerAborted(BodyPipe &); | |
774c051c | 146 | |
147 | // comm handlers | |
148 | virtual void handleCommConnected(); | |
149 | virtual void handleCommWrote(size_t size); | |
150 | virtual void handleCommRead(size_t size); | |
151 | void handleCommWroteHeaders(); | |
152 | void handleCommWroteBody(); | |
153 | ||
154 | // service waiting | |
155 | void noteServiceReady(); | |
156 | ||
5f8252d2 | 157 | public: |
158 | ICAPInOut virgin; | |
159 | ICAPInOut adapted; | |
160 | ||
478cfe99 | 161 | protected: |
162 | // bypasses exceptions if needed and possible | |
163 | virtual void callException(const TextException &e); | |
164 | ||
774c051c | 165 | private: |
5f8252d2 | 166 | virtual void start(); |
167 | ||
774c051c | 168 | void estimateVirginBody(); |
5f8252d2 | 169 | void makeAdaptedBodyPipe(const char *what); |
774c051c | 170 | |
171 | void waitForService(); | |
172 | ||
173 | // will not send anything [else] on the adapted pipe | |
174 | bool doneSending() const; | |
175 | ||
176 | void startWriting(); | |
177 | void writeMore(); | |
5f8252d2 | 178 | void writePreviewBody(); |
774c051c | 179 | void writePrimeBody(); |
180 | void writeSomeBody(const char *label, size_t size); | |
181 | ||
182 | void startReading(); | |
183 | void readMore(); | |
184 | virtual bool doneReading() const { return commEof || state.doneParsing(); } | |
c99de607 | 185 | virtual bool doneWriting() const { return state.doneWriting(); } |
774c051c | 186 | |
5f8252d2 | 187 | size_t virginContentSize(const VirginBodyAct &act) const; |
188 | const char *virginContentData(const VirginBodyAct &act) const; | |
189 | bool virginBodyEndReached(const VirginBodyAct &act) const; | |
190 | ||
774c051c | 191 | void makeRequestHeaders(MemBuf &buf); |
5f8252d2 | 192 | void makeUsernameHeader(const HttpRequest *request, MemBuf &buf); |
774c051c | 193 | void addLastRequestChunk(MemBuf &buf); |
c99de607 | 194 | void openChunk(MemBuf &buf, size_t chunkSize, bool ieof); |
195 | void closeChunk(MemBuf &buf); | |
774c051c | 196 | void virginConsume(); |
5f8252d2 | 197 | void finishNullOrEmptyBodyPreview(MemBuf &buf); |
774c051c | 198 | |
c824c43b | 199 | void decideOnPreview(); |
200 | void decideOnRetries(); | |
774c051c | 201 | bool shouldAllow204(); |
c824c43b | 202 | bool canBackupEverything() const; |
203 | ||
774c051c | 204 | void prepBackup(size_t expectedSize); |
205 | void backup(const MemBuf &buf); | |
206 | ||
207 | void parseMore(); | |
208 | ||
209 | void parseHeaders(); | |
210 | void parseIcapHead(); | |
211 | void parseHttpHead(); | |
212 | bool parseHead(HttpMsg *head); | |
5f8252d2 | 213 | void inheritVirginProperties(HttpRequest &newR, const HttpRequest &oldR); |
774c051c | 214 | |
5f8252d2 | 215 | void decideOnParsingBody(); |
774c051c | 216 | void parseBody(); |
774c051c | 217 | void maybeAllocateHttpMsg(); |
218 | ||
219 | void handle100Continue(); | |
b559db5d | 220 | bool validate200Ok(); |
774c051c | 221 | void handle200Ok(); |
222 | void handle204NoContent(); | |
223 | void handleUnknownScode(); | |
224 | ||
478cfe99 | 225 | void bypassFailure(); |
226 | ||
227 | void startSending(); | |
228 | void disableBypass(const char *reason); | |
229 | ||
230 | void prepEchoing(); | |
774c051c | 231 | void echoMore(); |
232 | ||
233 | virtual bool doneAll() const; | |
5f8252d2 | 234 | virtual void swanSong(); |
774c051c | 235 | |
774c051c | 236 | void stopReceiving(); |
237 | void stopSending(bool nicely); | |
c99de607 | 238 | void stopWriting(bool nicely); |
774c051c | 239 | void stopParsing(); |
240 | void stopBackup(); | |
241 | ||
242 | virtual void fillPendingStatus(MemBuf &buf) const; | |
243 | virtual void fillDoneStatus(MemBuf &buf) const; | |
3cfc19b3 | 244 | virtual bool fillVirginHttpHeader(MemBuf&) const; |
774c051c | 245 | |
246 | private: | |
247 | void packHead(MemBuf &httpBuf, const HttpMsg *head); | |
248 | void encapsulateHead(MemBuf &icapBuf, const char *section, MemBuf &httpBuf, const HttpMsg *head); | |
249 | bool gotEncapsulated(const char *section) const; | |
5f8252d2 | 250 | void checkConsuming(); |
774c051c | 251 | |
774c051c | 252 | |
253 | HttpReply *icapReply; | |
254 | ||
255 | SizedEstimate virginBody; | |
5f8252d2 | 256 | VirginBodyAct virginBodyWriting; // virgin body writing state |
257 | VirginBodyAct virginBodySending; // virgin body sending state | |
258 | size_t virginConsumed; // virgin data consumed so far | |
774c051c | 259 | ICAPPreview preview; // use for creating (writing) the preview |
260 | ||
261 | ChunkedCodingParser *bodyParser; // ICAP response body parser | |
262 | ||
478cfe99 | 263 | bool canStartBypass; // enables bypass of transaction failures |
264 | ||
774c051c | 265 | class State |
266 | { | |
267 | ||
268 | public: | |
269 | State(); | |
270 | ||
271 | public: | |
272 | ||
5f8252d2 | 273 | bool serviceWaiting; // waiting for ICAP service options |
274 | bool allowedPostview204; // mmust handle 204 No Content outside preview | |
774c051c | 275 | |
276 | // will not write anything [else] to the ICAP server connection | |
c99de607 | 277 | bool doneWriting() const { return writing == writingReallyDone; } |
774c051c | 278 | |
5f8252d2 | 279 | // will not use virgin.body_pipe |
280 | bool doneConsumingVirgin() const { return writing >= writingAlmostDone | |
281 | && (sending == sendingAdapted || sending == sendingDone); } | |
282 | ||
774c051c | 283 | // parsed entire ICAP response from the ICAP server |
284 | bool doneParsing() const { return parsing == psDone; } | |
285 | ||
286 | // is parsing ICAP or HTTP headers read from the ICAP server | |
287 | bool parsingHeaders() const | |
288 | { | |
289 | return parsing == psIcapHeader || | |
290 | parsing == psHttpHeader; | |
291 | } | |
292 | ||
293 | enum Parsing { psIcapHeader, psHttpHeader, psBody, psDone } parsing; | |
294 | ||
295 | // measures ICAP request writing progress | |
296 | enum Writing { writingInit, writingConnect, writingHeaders, | |
c99de607 | 297 | writingPreview, writingPaused, writingPrime, |
298 | writingAlmostDone, // waiting for the last write() call to finish | |
299 | writingReallyDone } writing; | |
774c051c | 300 | |
301 | enum Sending { sendingUndecided, sendingVirgin, sendingAdapted, | |
302 | sendingDone } sending; | |
303 | } | |
304 | ||
305 | state; | |
306 | ||
307 | CBDATA_CLASS2(ICAPModXact); | |
308 | }; | |
309 | ||
c824c43b | 310 | // An ICAPLauncher that stores ICAPModXact construction info and |
311 | // creates ICAPModXact when needed | |
312 | class ICAPModXactLauncher: public ICAPLauncher | |
313 | { | |
314 | public: | |
315 | ICAPModXactLauncher(ICAPInitiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, ICAPServiceRep::Pointer &s); | |
316 | ||
317 | protected: | |
318 | virtual ICAPXaction *createXaction(); | |
319 | ||
320 | ICAPInOut virgin; | |
321 | ||
322 | private: | |
323 | CBDATA_CLASS2(ICAPModXactLauncher); | |
324 | }; | |
774c051c | 325 | |
326 | #endif /* SQUID_ICAPMOD_XACT_H */ |