ModXact.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 #ifndef SQUID_ICAPMODXACT_H
10 #define SQUID_ICAPMODXACT_H
11 
12 #include "AccessLogEntry.h"
13 #include "adaptation/icap/InOut.h"
16 #include "BodyPipe.h"
17 #include "http/one/forward.h"
19 
20 /*
21  * ICAPModXact implements ICAP REQMOD and RESPMOD transaction using
22  * ICAPXaction as the base. The ICAPModXact receives a virgin HTTP message
23  * from an ICAP vecoring point, (a.k.a., initiator), communicates with the
24  * ICAP server, and sends the adapted HTTP message headers back.
25  * Virgin/adapted HTTP message body is reveived/sent using BodyPipe
26  * interface. The initiator (or its associate) is expected to send and/or
27  * receive the HTTP body.
28  */
29 
30 namespace Adaptation
31 {
32 namespace Icap
33 {
34 
35 // estimated future presence and size of something (e.g., HTTP body)
36 
38 {
39 
40 public:
41  SizedEstimate(); // not expected by default
42  void expect(int64_t aSize); // expect with any, even unknown size
43  bool expected() const;
44 
45  /* other members can be accessed iff expected() */
46 
47  bool knownSize() const;
48  uint64_t size() const; // can be accessed iff knownSize()
49 
50 private:
51  enum { dtUnexpected = -2, dtUnknown = -1 };
52  int64_t theData; // combines expectation and size info to save RAM
53 };
54 
55 // Virgin body may be used for two activities: (a) writing preview or prime
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.
61 {
62 
63 public:
64  VirginBodyAct();
65 
66  void plan(); // the activity may happen; do not consume at or above offset
67  void disable(); // the activity will not continue; no consumption restrictions
68 
69  bool active() const { return theState == stActive; }
70  bool disabled() const { return theState == stDisabled; }
71 
72  // methods below require active()
73 
74  uint64_t offset() const; // the absolute beginning of not-yet-acted-on data
75  void progress(size_t size); // note processed body bytes
76 
77 private:
78  int64_t theStart; // unprocessed virgin body data offset
79 
80  typedef enum { stUndecided, stActive, stDisabled } State;
81  State theState;
82 };
83 
84 // maintains preview-related sizes
85 
86 class Preview
87 {
88 
89 public:
90  Preview(); // disabled
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 
101  void wrote(size_t size, bool wroteEof);
102 
103 private:
104  size_t theWritten;
105  size_t theAd;
106  enum State { stDisabled, stWriting, stIeof, stDone } theState;
107 };
108 
111 {
112 public:
113  TrailerParser() : trailer(hoReply), hdr_sz(0) {}
118  bool parse(const char *buf, int len, int atEnd, Http::StatusCode *error);
121  size_t hdr_sz; // pedantic XXX: wrong type dictated by HttpHeader::parse() API
122 };
123 
126 {
127 public:
128  /* Http1::ChunkExtensionValueParser API */
129  virtual void parse(Tokenizer &tok, const SBuf &extName) override;
130 
131  bool sawUseOriginalBody() const { return useOriginalBody_ >= 0; }
132  uint64_t useOriginalBody() const { assert(sawUseOriginalBody()); return static_cast<uint64_t>(useOriginalBody_); }
133 
134 private:
135  static const SBuf UseOriginalBodyName;
136 
138  int64_t useOriginalBody_ = -1;
139 };
140 
141 class ModXact: public Xaction, public BodyProducer, public BodyConsumer
142 {
144 
145 public:
146  ModXact(Http::Message *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp, ServiceRep::Pointer &s);
147  virtual ~ModXact();
148 
149  // BodyProducer methods
150  virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer);
151  virtual void noteBodyConsumerAborted(BodyPipe::Pointer);
152 
153  // BodyConsumer methods
154  virtual void noteMoreBodyDataAvailable(BodyPipe::Pointer);
155  virtual void noteBodyProductionEnded(BodyPipe::Pointer);
156  virtual void noteBodyProducerAborted(BodyPipe::Pointer);
157 
158  // comm handlers
159  virtual void handleCommConnected();
160  virtual void handleCommWrote(size_t size);
161  virtual void handleCommRead(size_t size);
162  void handleCommWroteHeaders();
163  void handleCommWroteBody();
164 
165  // service waiting
166  void noteServiceReady();
167  void noteServiceAvailable();
168 
169 public:
172 
173  // bypasses exceptions if needed and possible
174  virtual void callException(const std::exception &e);
175 
177  virtual void detailError(int errDetail);
178  // Icap::Xaction API
179  virtual void clearError();
181  virtual AccessLogEntry::Pointer masterLogEntry() { return alMaster; }
182 
183 private:
184  virtual void start();
185 
187  const HttpRequest &virginRequest() const; // Must always be available
188 
189  void estimateVirginBody();
190  void makeAdaptedBodyPipe(const char *what);
191 
192  void waitForService();
193 
194  // will not send anything [else] on the adapted pipe
195  bool doneSending() const;
196 
197  void startWriting();
198  void writeMore();
199  void writePreviewBody();
200  void writePrimeBody();
201  void writeSomeBody(const char *label, size_t size);
202  void decideWritingAfterPreview(const char *previewKind);
203 
204  void startReading();
205  void readMore();
206  virtual bool doneReading() const { return commEof || state.doneParsing(); }
207  virtual bool doneWriting() const { return state.doneWriting(); }
208 
209  size_t virginContentSize(const VirginBodyAct &act) const;
210  const char *virginContentData(const VirginBodyAct &act) const;
211  bool virginBodyEndReached(const VirginBodyAct &act) const;
212 
213  void makeRequestHeaders(MemBuf &buf);
214  void makeAllowHeader(MemBuf &buf);
215  void makeUsernameHeader(const HttpRequest *request, MemBuf &buf);
216  void addLastRequestChunk(MemBuf &buf);
217  void openChunk(MemBuf &buf, size_t chunkSize, bool ieof);
218  void closeChunk(MemBuf &buf);
219  void virginConsume();
220  void finishNullOrEmptyBodyPreview(MemBuf &buf);
221 
222  void decideOnPreview();
223  void decideOnRetries();
224  bool shouldAllow204();
225  bool shouldAllow206any();
226  bool shouldAllow206in();
227  bool shouldAllow206out();
228  bool canBackupEverything() const;
229 
230  void prepBackup(size_t expectedSize);
231  void backup(const MemBuf &buf);
232 
233  void parseMore();
234 
235  void parseHeaders();
236  void parseIcapHead();
237  void parseHttpHead();
238  bool parseHead(Http::Message *head);
239 
240  void decideOnParsingBody();
241  void parseBody();
242  void parseIcapTrailer();
243  void maybeAllocateHttpMsg();
244 
245  void handle100Continue();
246  bool validate200Ok();
247  void handle200Ok();
248  void handle204NoContent();
249  void handle206PartialContent();
250  void handleUnknownScode();
251 
252  void bypassFailure();
253 
254  void startSending();
255  void disableBypass(const char *reason, bool includeGroupBypass);
256 
257  void prepEchoing();
258  void prepPartialBodyEchoing(uint64_t pos);
259  void echoMore();
260  void updateSources();
261 
262  virtual bool doneAll() const;
263  virtual void swanSong();
264 
265  void stopReceiving();
266  void stopSending(bool nicely);
267  void stopWriting(bool nicely);
268  void stopParsing(const bool checkUnparsedData = true);
269  void stopBackup();
270 
271  virtual void fillPendingStatus(MemBuf &buf) const;
272  virtual void fillDoneStatus(MemBuf &buf) const;
273  virtual bool fillVirginHttpHeader(MemBuf&) const;
274 
275 private:
280  template<class Part>
281  bool parsePart(Part *part, const char *description);
282 
283  void packHead(MemBuf &httpBuf, const Http::Message *head);
284  void encapsulateHead(MemBuf &icapBuf, const char *section, MemBuf &httpBuf, const Http::Message *head);
285  bool gotEncapsulated(const char *section) const;
287  bool expectHttpHeader() const;
289  bool expectHttpBody() const;
291  bool expectIcapTrailers() const;
292  void checkConsuming();
293 
294  virtual void finalizeLogInfo();
295 
297  VirginBodyAct virginBodyWriting; // virgin body writing state
298  VirginBodyAct virginBodySending; // virgin body sending state
299  uint64_t virginConsumed; // virgin data consumed so far
300  Preview preview; // use for creating (writing) the preview
301 
302  Http1::TeChunkedParser *bodyParser; // ICAP response body parser
303 
304  bool canStartBypass; // enables bypass of transaction failures
305  bool protectGroupBypass; // protects ServiceGroup-wide bypass of failures
306 
317 
319 
321 
323 
324  class State
325  {
326 
327  public:
328  State();
329 
330  public:
331 
332  bool serviceWaiting; // waiting for ICAP service options
333  bool allowedPostview204; // mmust handle 204 No Content outside preview
334  bool allowedPostview206; // must handle 206 Partial Content outside preview
335  bool allowedPreview206; // must handle 206 Partial Content inside preview
336  bool readyForUob;
338 
339  // will not write anything [else] to the ICAP server connection
340  bool doneWriting() const { return writing == writingReallyDone; }
341 
342  // will not use virgin.body_pipe
343  bool doneConsumingVirgin() const {
344  return writing >= writingAlmostDone
345  && ((sending == sendingAdapted && !readyForUob) ||
346  sending == sendingDone);
347  }
348 
349  // parsed entire ICAP response from the ICAP server
350  bool doneParsing() const { return parsing == psDone; }
351 
352  // is parsing ICAP or HTTP headers read from the ICAP server
353  bool parsingHeaders() const {
354  return parsing == psIcapHeader ||
355  parsing == psHttpHeader;
356  }
357 
358  enum Parsing { psIcapHeader, psHttpHeader, psBody, psIcapTrailer, psDone } parsing;
359 
360  // measures ICAP request writing progress
361  enum Writing { writingInit, writingConnect, writingHeaders,
362  writingPreview, writingPaused, writingPrime,
363  writingAlmostDone, // waiting for the last write() call to finish
364  writingReallyDone
365  } writing;
366 
367  enum Sending { sendingUndecided, sendingVirgin, sendingAdapted,
368  sendingDone
369  } sending;
370  } state;
371 
373 };
374 
375 // An Launcher that stores ModXact construction info and
376 // creates ModXact when needed
378 {
380 
381 public:
383 
384 protected:
385  virtual Xaction *createXaction();
386 
387  virtual void swanSong();
388 
390  void updateHistory(bool start);
391 
393 
395 };
396 
397 } // namespace Icap
398 } // namespace Adaptation
399 
400 #endif /* SQUID_ICAPMOD_XACT_H */
401 
VirginBodyAct virginBodySending
Definition: ModXact.h:298
size_t hdr_sz
parsed trailer size if parse() was successful
Definition: ModXact.h:121
#define assert(EX)
Definition: assert.h:17
State
Definition: cf_gen.cc:53
Parses and stores ICAP trailer header block.
Definition: ModXact.h:110
Definition: SBuf.h:86
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
void error(char *format,...)
static struct node * parse(FILE *fp)
Definition: parse.c:995
void expect(int64_t aSize)
Definition: ModXact.cc:1877
VirginBodyAct virginBodyWriting
Definition: ModXact.h:297
StatusCode
Definition: StatusCode.h:20
#define CBDATA_CLASS(type)
Definition: cbdata.h:302
common parts of HttpRequest and HttpReply
Definition: Message.h:25
Definition: parse.c:160
int adaptHistoryId
adaptation history slot reservation
Definition: ModXact.h:318
SizedEstimate virginBody
Definition: ModXact.h:296
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
virtual AccessLogEntry::Pointer masterLogEntry()
The master transaction log entry.
Definition: ModXact.h:181
void const char * buf
Definition: stub_helper.cc:16
virtual bool doneReading() const
Definition: ModXact.h:206
AccessLogEntry::Pointer al
Definition: ModXact.h:394
handles ICAP-specific chunk extensions supported by Squid
Definition: ModXact.h:125
Http1::TeChunkedParser * bodyParser
Definition: ModXact.h:302
Definition: MemBuf.h:23
AccessLogEntry::Pointer alMaster
Master transaction AccessLogEntry.
Definition: ModXact.h:372
virtual bool doneWriting() const
Definition: ModXact.h:207
bool doneConsumingVirgin() const
Definition: ModXact.h:343
ChunkExtensionValueParser extensionParser
Definition: ModXact.h:322
bool readyForUob
got a 206 response and expect a use-origin-body
Definition: ModXact.h:336
bool waitedForService
true if was queued at least once
Definition: ModXact.h:337
squidaio_request_t * head
Definition: aiops.cc:127
TrailerParser * trailerParser
Definition: ModXact.h:320

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors