]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/adaptation/icap/ModXact.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / adaptation / icap / ModXact.h
index a5e00616adb0e502667de1af74f3d32f0c621e0f..fdac7a0e980fae09610e5f67fb91f12c29f7c489 100644 (file)
@@ -1,43 +1,20 @@
-
 /*
- * $Id$
- *
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
  *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_ICAPMODXACT_H
 #define SQUID_ICAPMODXACT_H
 
-#include "BodyPipe.h"
-#include "adaptation/icap/Xaction.h"
+#include "AccessLogEntry.h"
 #include "adaptation/icap/InOut.h"
 #include "adaptation/icap/Launcher.h"
+#include "adaptation/icap/Xaction.h"
+#include "BodyPipe.h"
+#include "http/one/forward.h"
 
 /*
  * ICAPModXact implements ICAP REQMOD and RESPMOD transaction using
  * receive the HTTP body.
  */
 
-
-class ChunkedCodingParser;
-
-namespace Adaptation {
-namespace Icap {
+namespace Adaptation
+{
+namespace Icap
+{
 
 // estimated future presence and size of something (e.g., HTTP body)
 
@@ -104,7 +80,6 @@ private:
     State theState;
 };
 
-
 // maintains preview-related sizes
 
 class Preview
@@ -130,11 +105,28 @@ private:
     enum State { stDisabled, stWriting, stIeof, stDone } theState;
 };
 
+/// Parses and stores ICAP trailer header block.
+class TrailerParser
+{
+public:
+    TrailerParser() : trailer(hoReply), hdr_sz(0) {}
+    /// Parses trailers stored in a buffer.
+    /// \returns true and sets hdr_sz on success
+    /// \returns false and sets *error to zero when needs more data
+    /// \returns false and sets *error to a positive Http::StatusCode on error
+    bool parse(const char *buf, int len, int atEnd, Http::StatusCode *error);
+    HttpHeader trailer;
+    /// parsed trailer size if parse() was successful
+    size_t hdr_sz; // pedantic XXX: wrong type dictated by HttpHeader::parse() API
+};
+
 class ModXact: public Xaction, public BodyProducer, public BodyConsumer
 {
+    CBDATA_CLASS(ModXact);
 
 public:
-    ModXact(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, ServiceRep::Pointer &s);
+    ModXact(HttpMsg *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp, ServiceRep::Pointer &s);
+    virtual ~ModXact();
 
     // BodyProducer methods
     virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer);
@@ -154,18 +146,28 @@ public:
 
     // service waiting
     void noteServiceReady();
+    void noteServiceAvailable();
 
 public:
     InOut virgin;
     InOut adapted;
 
-protected:
     // bypasses exceptions if needed and possible
     virtual void callException(const std::exception &e);
 
+    /// record error detail in the virgin request if possible
+    virtual void detailError(int errDetail);
+    // Icap::Xaction API
+    virtual void clearError();
+    /// The master transaction log entry
+    virtual AccessLogEntry::Pointer masterLogEntry() { return alMaster; }
+
 private:
     virtual void start();
 
+    /// locates the request, either as a cause or as a virgin message itself
+    const HttpRequest &virginRequest() const; // Must always be available
+
     void estimateVirginBody();
     void makeAdaptedBodyPipe(const char *what);
 
@@ -179,6 +181,7 @@ private:
     void writePreviewBody();
     void writePrimeBody();
     void writeSomeBody(const char *label, size_t size);
+    void decideWritingAfterPreview(const char *previewKind);
 
     void startReading();
     void readMore();
@@ -190,6 +193,7 @@ private:
     bool virginBodyEndReached(const VirginBodyAct &act) const;
 
     void makeRequestHeaders(MemBuf &buf);
+    void makeAllowHeader(MemBuf &buf);
     void makeUsernameHeader(const HttpRequest *request, MemBuf &buf);
     void addLastRequestChunk(MemBuf &buf);
     void openChunk(MemBuf &buf, size_t chunkSize, bool ieof);
@@ -200,6 +204,9 @@ private:
     void decideOnPreview();
     void decideOnRetries();
     bool shouldAllow204();
+    bool shouldAllow206any();
+    bool shouldAllow206in();
+    bool shouldAllow206out();
     bool canBackupEverything() const;
 
     void prepBackup(size_t expectedSize);
@@ -214,21 +221,25 @@ private:
 
     void decideOnParsingBody();
     void parseBody();
+    void parseIcapTrailer();
     void maybeAllocateHttpMsg();
 
     void handle100Continue();
     bool validate200Ok();
     void handle200Ok();
     void handle204NoContent();
+    void handle206PartialContent();
     void handleUnknownScode();
 
     void bypassFailure();
 
     void startSending();
-    void disableBypass(const char *reason);
+    void disableBypass(const char *reason, bool includeGroupBypass);
 
     void prepEchoing();
+    void prepPartialBodyEchoing(uint64_t pos);
     void echoMore();
+    void updateSources(); ///< Update the HttpMsg sources
 
     virtual bool doneAll() const;
     virtual void swanSong();
@@ -236,7 +247,7 @@ private:
     void stopReceiving();
     void stopSending(bool nicely);
     void stopWriting(bool nicely);
-    void stopParsing();
+    void stopParsing(const bool checkUnparsedData = true);
     void stopBackup();
 
     virtual void fillPendingStatus(MemBuf &buf) const;
@@ -244,13 +255,25 @@ private:
     virtual bool fillVirginHttpHeader(MemBuf&) const;
 
 private:
+    /// parses a message header or trailer
+    /// \returns true on success
+    /// \returns false if more data is needed
+    /// \throw TextException on unrecoverable error
+    template<class Part>
+    bool parsePart(Part *part, const char *description);
+
     void packHead(MemBuf &httpBuf, const HttpMsg *head);
     void encapsulateHead(MemBuf &icapBuf, const char *section, MemBuf &httpBuf, const HttpMsg *head);
     bool gotEncapsulated(const char *section) const;
+    /// whether ICAP response header indicates HTTP header presence
+    bool expectHttpHeader() const;
+    /// whether ICAP response header indicates HTTP body presence
+    bool expectHttpBody() const;
+    /// whether ICAP response header indicates ICAP trailers presence
+    bool expectIcapTrailers() const;
     void checkConsuming();
 
-
-    HttpReply *icapReply;
+    virtual void finalizeLogInfo();
 
     SizedEstimate virginBody;
     VirginBodyAct virginBodyWriting; // virgin body writing state
@@ -258,9 +281,25 @@ private:
     uint64_t virginConsumed;        // virgin data consumed so far
     Preview preview; // use for creating (writing) the preview
 
-    ChunkedCodingParser *bodyParser; // ICAP response body parser
+    Http1::TeChunkedParser *bodyParser; // ICAP response body parser
 
     bool canStartBypass; // enables bypass of transaction failures
+    bool protectGroupBypass; // protects ServiceGroup-wide bypass of failures
+
+    /**
+     * size of HTTP header in ICAP reply or -1 if there is not any encapsulated
+     * message data
+     */
+    int64_t replyHttpHeaderSize;
+    /**
+     * size of dechunked HTTP body in ICAP reply or -1 if there is not any
+     * encapsulated message data
+     */
+    int64_t replyHttpBodySize;
+
+    int adaptHistoryId; ///< adaptation history slot reservation
+
+    TrailerParser *trailerParser;
 
     class State
     {
@@ -272,6 +311,10 @@ private:
 
         bool serviceWaiting; // waiting for ICAP service options
         bool allowedPostview204; // mmust handle 204 No Content outside preview
+        bool allowedPostview206; // must handle 206 Partial Content outside preview
+        bool allowedPreview206; // must handle 206 Partial Content inside preview
+        bool readyForUob; ///< got a 206 response and expect a use-origin-body
+        bool waitedForService; ///< true if was queued at least once
 
         // will not write anything [else] to the ICAP server connection
         bool doneWriting() const { return writing == writingReallyDone; }
@@ -279,7 +322,8 @@ private:
         // will not use virgin.body_pipe
         bool doneConsumingVirgin() const {
             return writing >= writingAlmostDone
-                   && (sending == sendingAdapted || sending == sendingDone);
+                   && ((sending == sendingAdapted && !readyForUob) ||
+                       sending == sendingDone);
         }
 
         // parsed entire ICAP response from the ICAP server
@@ -291,7 +335,7 @@ private:
                    parsing == psHttpHeader;
         }
 
-        enum Parsing { psIcapHeader, psHttpHeader, psBody, psDone } parsing;
+        enum Parsing { psIcapHeader, psHttpHeader, psBody, psIcapTrailer, psDone } parsing;
 
         // measures ICAP request writing progress
         enum Writing { writingInit, writingConnect, writingHeaders,
@@ -305,27 +349,33 @@ private:
                      } sending;
     } state;
 
-    CBDATA_CLASS2(ModXact);
+    AccessLogEntry::Pointer alMaster; ///< Master transaction AccessLogEntry
 };
 
 // An Launcher that stores ModXact construction info and
 // creates ModXact when needed
 class ModXactLauncher: public Launcher
 {
+    CBDATA_CLASS(ModXactLauncher);
+
 public:
-    ModXactLauncher(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer s);
+    ModXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp, Adaptation::ServicePointer s);
 
 protected:
     virtual Xaction *createXaction();
 
+    virtual void swanSong();
+
+    /// starts or stops transaction accounting in ICAP history
+    void updateHistory(bool start);
+
     InOut virgin;
 
-private:
-    CBDATA_CLASS2(ModXactLauncher);
+    AccessLogEntry::Pointer al;
 };
 
-
 } // namespace Icap
 } // namespace Adaptation
 
 #endif /* SQUID_ICAPMOD_XACT_H */
+