6 * SQUID Web Proxy Cache http://www.squid-cache.org/
7 * ----------------------------------------------------------
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
16 * sources; see the CREDITS file for full details.
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.
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.
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.
34 #ifndef SQUID_ICAPMODXACT_H
35 #define SQUID_ICAPMODXACT_H
38 #include "adaptation/icap/Xaction.h"
39 #include "adaptation/icap/InOut.h"
40 #include "adaptation/icap/Launcher.h"
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.
52 class ChunkedCodingParser
;
59 // estimated future presence and size of something (e.g., HTTP body)
65 SizedEstimate(); // not expected by default
66 void expect(int64_t aSize
); // expect with any, even unknown size
67 bool expected() const;
69 /* other members can be accessed iff expected() */
71 bool knownSize() const;
72 uint64_t size() const; // can be accessed iff knownSize()
75 enum { dtUnexpected
= -2, dtUnknown
= -1 };
76 int64_t theData
; // combines expectation and size info to save RAM
79 // Virgin body may be used for two activities: (a) writing preview or prime
80 // body to the ICAP server and (b) sending the body back in the echo mode.
81 // Both activities use the same BodyPipe and may be active at the same time.
82 // This class is used to maintain the state of body writing or sending
83 // activity and to coordinate consumption of the shared virgin body buffer.
90 void plan(); // the activity may happen; do not consume at or above offset
91 void disable(); // the activity wont continue; no consumption restrictions
93 bool active() const { return theState
== stActive
; }
94 bool disabled() const { return theState
== stDisabled
; }
96 // methods below require active()
98 uint64_t offset() const; // the absolute beginning of not-yet-acted-on data
99 void progress(size_t size
); // note processed body bytes
102 int64_t theStart
; // unprocessed virgin body data offset
104 typedef enum { stUndecided
, stActive
, stDisabled
} State
;
108 // maintains preview-related sizes
114 Preview(); // disabled
115 void enable(size_t anAd
); // enabled with advertised size
116 bool enabled() const;
118 /* other members can be accessed iff enabled() */
120 size_t ad() const; // advertised preview size
121 size_t debt() const; // remains to write
122 bool done() const; // wrote everything
123 bool ieof() const; // premature EOF
125 void wrote(size_t size
, bool wroteEof
);
130 enum State
{ stDisabled
, stWriting
, stIeof
, stDone
} theState
;
133 class ModXact
: public Xaction
, public BodyProducer
, public BodyConsumer
137 ModXact(HttpMsg
*virginHeader
, HttpRequest
*virginCause
, ServiceRep::Pointer
&s
);
140 // BodyProducer methods
141 virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer
);
142 virtual void noteBodyConsumerAborted(BodyPipe::Pointer
);
144 // BodyConsumer methods
145 virtual void noteMoreBodyDataAvailable(BodyPipe::Pointer
);
146 virtual void noteBodyProductionEnded(BodyPipe::Pointer
);
147 virtual void noteBodyProducerAborted(BodyPipe::Pointer
);
150 virtual void handleCommConnected();
151 virtual void handleCommWrote(size_t size
);
152 virtual void handleCommRead(size_t size
);
153 void handleCommWroteHeaders();
154 void handleCommWroteBody();
157 void noteServiceReady();
158 void noteServiceAvailable();
164 // bypasses exceptions if needed and possible
165 virtual void callException(const std::exception
&e
);
167 /// record error detail in the virgin request if possible
168 virtual void detailError(int errDetail
);
170 virtual void clearError();
173 virtual void start();
175 /// locates the request, either as a cause or as a virgin message itself
176 const HttpRequest
&virginRequest() const; // Must always be available
178 void estimateVirginBody();
179 void makeAdaptedBodyPipe(const char *what
);
181 void waitForService();
183 // will not send anything [else] on the adapted pipe
184 bool doneSending() const;
188 void writePreviewBody();
189 void writePrimeBody();
190 void writeSomeBody(const char *label
, size_t size
);
191 void decideWritingAfterPreview(const char *previewKind
);
195 virtual bool doneReading() const { return commEof
|| state
.doneParsing(); }
196 virtual bool doneWriting() const { return state
.doneWriting(); }
198 size_t virginContentSize(const VirginBodyAct
&act
) const;
199 const char *virginContentData(const VirginBodyAct
&act
) const;
200 bool virginBodyEndReached(const VirginBodyAct
&act
) const;
202 void makeRequestHeaders(MemBuf
&buf
);
203 void makeAllowHeader(MemBuf
&buf
);
204 void makeUsernameHeader(const HttpRequest
*request
, MemBuf
&buf
);
205 void addLastRequestChunk(MemBuf
&buf
);
206 void openChunk(MemBuf
&buf
, size_t chunkSize
, bool ieof
);
207 void closeChunk(MemBuf
&buf
);
208 void virginConsume();
209 void finishNullOrEmptyBodyPreview(MemBuf
&buf
);
211 void decideOnPreview();
212 void decideOnRetries();
213 bool shouldAllow204();
214 bool shouldAllow206any();
215 bool shouldAllow206in();
216 bool shouldAllow206out();
217 bool canBackupEverything() const;
219 void prepBackup(size_t expectedSize
);
220 void backup(const MemBuf
&buf
);
225 void parseIcapHead();
226 void parseHttpHead();
227 bool parseHead(HttpMsg
*head
);
229 void decideOnParsingBody();
231 void maybeAllocateHttpMsg();
233 void handle100Continue();
234 bool validate200Ok();
236 void handle204NoContent();
237 void handle206PartialContent();
238 void handleUnknownScode();
240 void bypassFailure();
243 void disableBypass(const char *reason
, bool includeGroupBypass
);
246 void prepPartialBodyEchoing(uint64_t pos
);
249 virtual bool doneAll() const;
250 virtual void swanSong();
252 void stopReceiving();
253 void stopSending(bool nicely
);
254 void stopWriting(bool nicely
);
258 virtual void fillPendingStatus(MemBuf
&buf
) const;
259 virtual void fillDoneStatus(MemBuf
&buf
) const;
260 virtual bool fillVirginHttpHeader(MemBuf
&) const;
263 void packHead(MemBuf
&httpBuf
, const HttpMsg
*head
);
264 void encapsulateHead(MemBuf
&icapBuf
, const char *section
, MemBuf
&httpBuf
, const HttpMsg
*head
);
265 bool gotEncapsulated(const char *section
) const;
266 void checkConsuming();
268 virtual void finalizeLogInfo();
270 SizedEstimate virginBody
;
271 VirginBodyAct virginBodyWriting
; // virgin body writing state
272 VirginBodyAct virginBodySending
; // virgin body sending state
273 uint64_t virginConsumed
; // virgin data consumed so far
274 Preview preview
; // use for creating (writing) the preview
276 ChunkedCodingParser
*bodyParser
; // ICAP response body parser
278 bool canStartBypass
; // enables bypass of transaction failures
279 bool protectGroupBypass
; // protects ServiceGroup-wide bypass of failures
282 * size of HTTP header in ICAP reply or -1 if there is not any encapsulated
285 int64_t replyHttpHeaderSize
;
287 * size of dechunked HTTP body in ICAP reply or -1 if there is not any
288 * encapsulated message data
290 int64_t replyHttpBodySize
;
292 int adaptHistoryId
; ///< adaptation history slot reservation
302 bool serviceWaiting
; // waiting for ICAP service options
303 bool allowedPostview204
; // mmust handle 204 No Content outside preview
304 bool allowedPostview206
; // must handle 206 Partial Content outside preview
305 bool allowedPreview206
; // must handle 206 Partial Content inside preview
306 bool readyForUob
; ///< got a 206 response and expect a use-origin-body
307 bool waitedForService
; ///< true if was queued at least once
309 // will not write anything [else] to the ICAP server connection
310 bool doneWriting() const { return writing
== writingReallyDone
; }
312 // will not use virgin.body_pipe
313 bool doneConsumingVirgin() const {
314 return writing
>= writingAlmostDone
315 && ((sending
== sendingAdapted
&& !readyForUob
) ||
316 sending
== sendingDone
);
319 // parsed entire ICAP response from the ICAP server
320 bool doneParsing() const { return parsing
== psDone
; }
322 // is parsing ICAP or HTTP headers read from the ICAP server
323 bool parsingHeaders() const {
324 return parsing
== psIcapHeader
||
325 parsing
== psHttpHeader
;
328 enum Parsing
{ psIcapHeader
, psHttpHeader
, psBody
, psDone
} parsing
;
330 // measures ICAP request writing progress
331 enum Writing
{ writingInit
, writingConnect
, writingHeaders
,
332 writingPreview
, writingPaused
, writingPrime
,
333 writingAlmostDone
, // waiting for the last write() call to finish
337 enum Sending
{ sendingUndecided
, sendingVirgin
, sendingAdapted
,
342 CBDATA_CLASS2(ModXact
);
345 // An Launcher that stores ModXact construction info and
346 // creates ModXact when needed
347 class ModXactLauncher
: public Launcher
350 ModXactLauncher(HttpMsg
*virginHeader
, HttpRequest
*virginCause
, Adaptation::ServicePointer s
);
353 virtual Xaction
*createXaction();
355 virtual void swanSong();
357 /// starts or stops transaction accounting in ICAP history
358 void updateHistory(bool start
);
363 CBDATA_CLASS2(ModXactLauncher
);
367 } // namespace Adaptation
369 #endif /* SQUID_ICAPMOD_XACT_H */