2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_ICAPMODXACT_H
10 #define SQUID_ICAPMODXACT_H
12 #include "AccessLogEntry.h"
13 #include "adaptation/icap/InOut.h"
14 #include "adaptation/icap/Launcher.h"
15 #include "adaptation/icap/Xaction.h"
17 #include "http/one/forward.h"
20 * ICAPModXact implements ICAP REQMOD and RESPMOD transaction using
21 * ICAPXaction as the base. The ICAPModXact receives a virgin HTTP message
22 * from an ICAP vecoring point, (a.k.a., initiator), communicates with the
23 * ICAP server, and sends the adapted HTTP message headers back.
24 * Virgin/adapted HTTP message body is reveived/sent using BodyPipe
25 * interface. The initiator (or its associate) is expected to send and/or
26 * receive the HTTP body.
34 // estimated future presence and size of something (e.g., HTTP body)
40 SizedEstimate(); // not expected by default
41 void expect(int64_t aSize
); // expect with any, even unknown size
42 bool expected() const;
44 /* other members can be accessed iff expected() */
46 bool knownSize() const;
47 uint64_t size() const; // can be accessed iff knownSize()
50 enum { dtUnexpected
= -2, dtUnknown
= -1 };
51 int64_t theData
; // combines expectation and size info to save RAM
54 // Virgin body may be used for two activities: (a) writing preview or prime
55 // body to the ICAP server and (b) sending the body back in the echo mode.
56 // Both activities use the same BodyPipe and may be active at the same time.
57 // This class is used to maintain the state of body writing or sending
58 // activity and to coordinate consumption of the shared virgin body buffer.
65 void plan(); // the activity may happen; do not consume at or above offset
66 void disable(); // the activity wont continue; no consumption restrictions
68 bool active() const { return theState
== stActive
; }
69 bool disabled() const { return theState
== stDisabled
; }
71 // methods below require active()
73 uint64_t offset() const; // the absolute beginning of not-yet-acted-on data
74 void progress(size_t size
); // note processed body bytes
77 int64_t theStart
; // unprocessed virgin body data offset
79 typedef enum { stUndecided
, stActive
, stDisabled
} State
;
83 // maintains preview-related sizes
89 Preview(); // disabled
90 void enable(size_t anAd
); // enabled with advertised size
93 /* other members can be accessed iff enabled() */
95 size_t ad() const; // advertised preview size
96 size_t debt() const; // remains to write
97 bool done() const; // wrote everything
98 bool ieof() const; // premature EOF
100 void wrote(size_t size
, bool wroteEof
);
105 enum State
{ stDisabled
, stWriting
, stIeof
, stDone
} theState
;
108 class ModXact
: public Xaction
, public BodyProducer
, public BodyConsumer
110 CBDATA_CLASS(ModXact
);
113 ModXact(HttpMsg
*virginHeader
, HttpRequest
*virginCause
, AccessLogEntry::Pointer
&alp
, ServiceRep::Pointer
&s
);
116 // BodyProducer methods
117 virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer
);
118 virtual void noteBodyConsumerAborted(BodyPipe::Pointer
);
120 // BodyConsumer methods
121 virtual void noteMoreBodyDataAvailable(BodyPipe::Pointer
);
122 virtual void noteBodyProductionEnded(BodyPipe::Pointer
);
123 virtual void noteBodyProducerAborted(BodyPipe::Pointer
);
126 virtual void handleCommConnected();
127 virtual void handleCommWrote(size_t size
);
128 virtual void handleCommRead(size_t size
);
129 void handleCommWroteHeaders();
130 void handleCommWroteBody();
133 void noteServiceReady();
134 void noteServiceAvailable();
140 // bypasses exceptions if needed and possible
141 virtual void callException(const std::exception
&e
);
143 /// record error detail in the virgin request if possible
144 virtual void detailError(int errDetail
);
146 virtual void clearError();
149 virtual void start();
151 /// locates the request, either as a cause or as a virgin message itself
152 const HttpRequest
&virginRequest() const; // Must always be available
154 void estimateVirginBody();
155 void makeAdaptedBodyPipe(const char *what
);
157 void waitForService();
159 // will not send anything [else] on the adapted pipe
160 bool doneSending() const;
164 void writePreviewBody();
165 void writePrimeBody();
166 void writeSomeBody(const char *label
, size_t size
);
167 void decideWritingAfterPreview(const char *previewKind
);
171 virtual bool doneReading() const { return commEof
|| state
.doneParsing(); }
172 virtual bool doneWriting() const { return state
.doneWriting(); }
174 size_t virginContentSize(const VirginBodyAct
&act
) const;
175 const char *virginContentData(const VirginBodyAct
&act
) const;
176 bool virginBodyEndReached(const VirginBodyAct
&act
) const;
178 void makeRequestHeaders(MemBuf
&buf
);
179 void makeAllowHeader(MemBuf
&buf
);
180 void makeUsernameHeader(const HttpRequest
*request
, MemBuf
&buf
);
181 void addLastRequestChunk(MemBuf
&buf
);
182 void openChunk(MemBuf
&buf
, size_t chunkSize
, bool ieof
);
183 void closeChunk(MemBuf
&buf
);
184 void virginConsume();
185 void finishNullOrEmptyBodyPreview(MemBuf
&buf
);
187 void decideOnPreview();
188 void decideOnRetries();
189 bool shouldAllow204();
190 bool shouldAllow206any();
191 bool shouldAllow206in();
192 bool shouldAllow206out();
193 bool canBackupEverything() const;
195 void prepBackup(size_t expectedSize
);
196 void backup(const MemBuf
&buf
);
201 void parseIcapHead();
202 void parseHttpHead();
203 bool parseHead(HttpMsg
*head
);
205 void decideOnParsingBody();
207 void maybeAllocateHttpMsg();
209 void handle100Continue();
210 bool validate200Ok();
212 void handle204NoContent();
213 void handle206PartialContent();
214 void handleUnknownScode();
216 void bypassFailure();
219 void disableBypass(const char *reason
, bool includeGroupBypass
);
222 void prepPartialBodyEchoing(uint64_t pos
);
224 void updateSources(); ///< Update the HttpMsg sources
226 virtual bool doneAll() const;
227 virtual void swanSong();
229 void stopReceiving();
230 void stopSending(bool nicely
);
231 void stopWriting(bool nicely
);
235 virtual void fillPendingStatus(MemBuf
&buf
) const;
236 virtual void fillDoneStatus(MemBuf
&buf
) const;
237 virtual bool fillVirginHttpHeader(MemBuf
&) const;
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();
245 virtual void finalizeLogInfo();
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
253 Http1::TeChunkedParser
*bodyParser
; // ICAP response body parser
255 bool canStartBypass
; // enables bypass of transaction failures
256 bool protectGroupBypass
; // protects ServiceGroup-wide bypass of failures
259 * size of HTTP header in ICAP reply or -1 if there is not any encapsulated
262 int64_t replyHttpHeaderSize
;
264 * size of dechunked HTTP body in ICAP reply or -1 if there is not any
265 * encapsulated message data
267 int64_t replyHttpBodySize
;
269 int adaptHistoryId
; ///< adaptation history slot reservation
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
286 // will not write anything [else] to the ICAP server connection
287 bool doneWriting() const { return writing
== writingReallyDone
; }
289 // will not use virgin.body_pipe
290 bool doneConsumingVirgin() const {
291 return writing
>= writingAlmostDone
292 && ((sending
== sendingAdapted
&& !readyForUob
) ||
293 sending
== sendingDone
);
296 // parsed entire ICAP response from the ICAP server
297 bool doneParsing() const { return parsing
== psDone
; }
299 // is parsing ICAP or HTTP headers read from the ICAP server
300 bool parsingHeaders() const {
301 return parsing
== psIcapHeader
||
302 parsing
== psHttpHeader
;
305 enum Parsing
{ psIcapHeader
, psHttpHeader
, psBody
, psDone
} parsing
;
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
314 enum Sending
{ sendingUndecided
, sendingVirgin
, sendingAdapted
,
319 AccessLogEntry::Pointer alMaster
; ///< Master transaction AccessLogEntry
322 // An Launcher that stores ModXact construction info and
323 // creates ModXact when needed
324 class ModXactLauncher
: public Launcher
326 CBDATA_CLASS(ModXactLauncher
);
329 ModXactLauncher(HttpMsg
*virginHeader
, HttpRequest
*virginCause
, AccessLogEntry::Pointer
&alp
, Adaptation::ServicePointer s
);
332 virtual Xaction
*createXaction();
334 virtual void swanSong();
336 /// starts or stops transaction accounting in ICAP history
337 void updateHistory(bool start
);
341 AccessLogEntry::Pointer al
;
345 } // namespace Adaptation
347 #endif /* SQUID_ICAPMOD_XACT_H */