1 /* 2 * Copyright (C) 1996-2021 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_CLIENTSIDEREQUEST_H 10 #define SQUID_CLIENTSIDEREQUEST_H 11 12 #include "AccessLogEntry.h" 13 #include "acl/forward.h" 14 #include "client_side.h" 15 #include "clientStream.h" 16 #include "http/forward.h" 17 #include "HttpHeaderRange.h" 18 #include "LogTags.h" 19 20 #if USE_ADAPTATION 21 #include "adaptation/forward.h" 22 #include "adaptation/Initiator.h" 23 class HttpMsg; 24 #endif 25 26 class ClientRequestContext; 27 class ConnStateData; 28 class MemObject; 29 30 /* client_side_request.c - client side request related routines (pure logic) */ 31 int clientBeginRequest(const HttpRequestMethod&, char const *, CSCB *, CSD *, ClientStreamData, HttpHeader const *, char *, size_t, const MasterXactionPointer &); 32 33 class ClientHttpRequest 34 #if USE_ADAPTATION 35 : public Adaptation::Initiator, // to start adaptation transactions 36 public BodyConsumer // to receive reply bodies in request satisf. mode 37 #endif 38 { 39 CBDATA_CLASS(ClientHttpRequest); 40 41 public: 42 ClientHttpRequest(ConnStateData *csd); 43 ~ClientHttpRequest(); 44 /* Not implemented - present to prevent synthetic operations */ 45 ClientHttpRequest(ClientHttpRequest const &); 46 ClientHttpRequest& operator=(ClientHttpRequest const &); 47 48 String rangeBoundaryStr() const; 49 void freeResources(); 50 void updateCounters(); 51 void logRequest(); 52 _SQUID_INLINE_ MemObject * memObject() const; 53 bool multipartRangeRequest() const; 54 void processRequest(); 55 void httpStart(); 56 bool onlyIfCached()const; 57 bool gotEnough() const; 58 _SQUID_INLINE_ StoreEntry *storeEntry() const; 59 void storeEntry(StoreEntry *); 60 _SQUID_INLINE_ StoreEntry *loggingEntry() const; 61 void loggingEntry(StoreEntry *); 62 63 _SQUID_INLINE_ ConnStateData * getConn() const; 64 _SQUID_INLINE_ void setConn(ConnStateData *); 65 66 /// Initializes the current request with the virgin request. 67 /// Call this method when the virgin request becomes known. 68 /// To update the current request later, use resetRequest(). 69 void initRequest(HttpRequest *); 70 71 /// Resets the current request to the latest adapted or redirected 72 /// request. Call this every time adaptation or redirection changes 73 /// the request. To set the virgin request, use initRequest(). 74 void resetRequest(HttpRequest *); 75 76 /** Details of the client socket which produced us. 77 * Treat as read-only for the lifetime of this HTTP request. 78 */ 79 Comm::ConnectionPointer clientConnection; 80 81 /// Request currently being handled by ClientHttpRequest. 82 /// Starts as a virgin request; see initRequest(). 83 /// Usually remains nil until the virgin request header is parsed or faked. 84 /// Adaptation and redirections replace it; see resetRequest(). 85 HttpRequest * const request; 86 /// Usually starts as a URI received from the client, with scheme and host 87 /// added if needed. Is used to create the virgin request for initRequest(). 88 /// URIs of adapted/redirected requests replace it via resetRequest(). 89 char *uri; 90 91 // TODO: remove this field and store the URI directly in al->url 92 /// Cleaned up URI of the current (virgin or adapted/redirected) request, 93 /// computed URI of an internally-generated requests, or 94 /// one of the hard-coded "error:..." URIs. 95 char * const log_uri; 96 97 String store_id; /* StoreID for transactions where the request member is nil */ 98 99 struct Out { OutOut100 Out() : offset(0), size(0), headers_sz(0) {} 101 102 int64_t offset; 103 uint64_t size; 104 size_t headers_sz; 105 } out; 106 107 HttpHdrRangeIter range_iter; /* data for iterating thru range specs */ 108 size_t req_sz; /* raw request size on input, not current request size */ 109 110 /// the processing tags associated with this request transaction. 111 // NP: still an enum so each stage altering it must take care when replacing it. 112 LogTags logType; 113 114 AccessLogEntry::Pointer al; ///< access.log entry 115 116 struct Flags { FlagsFlags117 Flags() : accel(false), internal(false), done_copying(false), purging(false) {} 118 119 bool accel; 120 bool internal; 121 bool done_copying; 122 bool purging; 123 } flags; 124 125 struct Redirect { RedirectRedirect126 Redirect() : status(Http::scNone), location(NULL) {} 127 128 Http::StatusCode status; 129 char *location; 130 } redirect; 131 132 dlink_node active; 133 dlink_list client_stream; 134 int64_t mRangeCLen() const; 135 136 ClientRequestContext *calloutContext; 137 void doCallouts(); 138 139 // The three methods below prepare log_uri and friends for future logging. 140 // Call the best-fit method whenever the current request or its URI changes. 141 142 /// sets log_uri when we know the current request 143 void setLogUriToRequestUri(); 144 /// sets log_uri to a parsed request URI when Squid fails to parse or 145 /// validate other request components, yielding no current request 146 void setLogUriToRawUri(const char *rawUri, const HttpRequestMethod &); 147 /// sets log_uri and uri to an internally-generated "error:..." URI when 148 /// neither the current request nor the parsed request URI are known 149 void setErrorUri(const char *errorUri); 150 151 /// Prepares to satisfy a Range request with a generated HTTP 206 response. 152 /// Initializes range_iter state to allow raw range_iter access. 153 /// \returns Content-Length value for the future response; never negative 154 int64_t prepPartialResponseGeneration(); 155 156 /// Build an error reply. For use with the callouts. 157 void calloutsError(const err_type error, const int errDetail); 158 159 #if USE_ADAPTATION 160 // AsyncJob virtual methods doneAll()161 virtual bool doneAll() const { 162 return Initiator::doneAll() && 163 BodyConsumer::doneAll() && false; 164 } 165 virtual void callException(const std::exception &ex); 166 #endif 167 168 private: 169 /// assigns log_uri with aUri without copying the entire C-string 170 void absorbLogUri(char *aUri); 171 /// resets the current request and log_uri to nil 172 void clearRequest(); 173 /// initializes the current unassigned request to the virgin request 174 /// sets the current request, asserting that it was unset 175 void assignRequest(HttpRequest *aRequest); 176 177 int64_t maxReplyBodySize_; 178 StoreEntry *entry_; 179 StoreEntry *loggingEntry_; 180 ConnStateData * conn_; 181 182 #if USE_OPENSSL 183 /// whether (and how) the request needs to be bumped 184 Ssl::BumpMode sslBumpNeed_; 185 186 public: 187 /// returns raw sslBump mode value sslBumpNeed()188 Ssl::BumpMode sslBumpNeed() const { return sslBumpNeed_; } 189 /// returns true if and only if the request needs to be bumped sslBumpNeeded()190 bool sslBumpNeeded() const { return sslBumpNeed_ == Ssl::bumpServerFirst || sslBumpNeed_ == Ssl::bumpClientFirst || sslBumpNeed_ == Ssl::bumpBump || sslBumpNeed_ == Ssl::bumpPeek || sslBumpNeed_ == Ssl::bumpStare; } 191 /// set the sslBumpNeeded state 192 void sslBumpNeed(Ssl::BumpMode mode); 193 void sslBumpStart(); 194 void sslBumpEstablish(Comm::Flag errflag); 195 #endif 196 197 #if USE_ADAPTATION 198 199 public: 200 void startAdaptation(const Adaptation::ServiceGroupPointer &g); requestSatisfactionMode()201 bool requestSatisfactionMode() const { return request_satisfaction_mode; } 202 203 private: 204 /// Handles an adaptation client request failure. 205 /// Bypasses the error if possible, or build an error reply. 206 void handleAdaptationFailure(int errDetail, bool bypassable = false); 207 208 // Adaptation::Initiator API 209 virtual void noteAdaptationAnswer(const Adaptation::Answer &answer); 210 void handleAdaptedHeader(HttpMsg *msg); 211 void handleAdaptationBlock(const Adaptation::Answer &answer); 212 virtual void noteAdaptationAclCheckDone(Adaptation::ServiceGroupPointer group); 213 214 // BodyConsumer API, called by BodyPipe 215 virtual void noteMoreBodyDataAvailable(BodyPipe::Pointer); 216 virtual void noteBodyProductionEnded(BodyPipe::Pointer); 217 virtual void noteBodyProducerAborted(BodyPipe::Pointer); 218 219 void endRequestSatisfaction(); 220 /// called by StoreEntry when it has more buffer space available 221 void resumeBodyStorage(); 222 223 private: 224 CbcPointer<Adaptation::Initiate> virginHeadSource; 225 BodyPipe::Pointer adaptedBodySource; 226 227 bool request_satisfaction_mode; 228 int64_t request_satisfaction_offset; 229 #endif 230 }; 231 232 /* client http based routines */ 233 char *clientConstructTraceEcho(ClientHttpRequest *); 234 235 ACLFilledChecklist *clientAclChecklistCreate(const acl_access * acl,ClientHttpRequest * http); 236 int clientHttpRequestStatus(int fd, ClientHttpRequest const *http); 237 void clientAccessCheck(ClientHttpRequest *); 238 239 /* ones that should be elsewhere */ 240 void tunnelStart(ClientHttpRequest *); 241 242 #if _USE_INLINE_ 243 #include "client_side_request.cci" 244 #include "Store.h" 245 #endif 246 247 #endif /* SQUID_CLIENTSIDEREQUEST_H */ 248 249