]> git.ipfire.org Git - thirdparty/squid.git/blob - src/client_side_request.h
Handle more Range requests (#790)
[thirdparty/squid.git] / src / client_side_request.h
1 /*
2 * Copyright (C) 1996-2020 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 #include "Store.h"
20
21 #if USE_ADAPTATION
22 #include "adaptation/forward.h"
23 #include "adaptation/Initiator.h"
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 MemObject * memObject() const {
53 return (storeEntry() ? storeEntry()->mem_obj : nullptr);
54 }
55 bool multipartRangeRequest() const;
56 void processRequest();
57 void httpStart();
58 bool onlyIfCached()const;
59 bool gotEnough() const;
60 StoreEntry *storeEntry() const { return entry_; }
61 void storeEntry(StoreEntry *);
62 StoreEntry *loggingEntry() const { return loggingEntry_; }
63 void loggingEntry(StoreEntry *);
64
65 ConnStateData * getConn() const {
66 return (cbdataReferenceValid(conn_) ? conn_ : nullptr);
67 }
68
69 /// Initializes the current request with the virgin request.
70 /// Call this method when the virgin request becomes known.
71 /// To update the current request later, use resetRequest().
72 void initRequest(HttpRequest *);
73
74 /// Resets the current request to the latest adapted or redirected
75 /// request. Call this every time adaptation or redirection changes
76 /// the request. To set the virgin request, use initRequest().
77 void resetRequest(HttpRequest *);
78
79 /** Details of the client socket which produced us.
80 * Treat as read-only for the lifetime of this HTTP request.
81 */
82 Comm::ConnectionPointer clientConnection;
83
84 /// Request currently being handled by ClientHttpRequest.
85 /// Usually remains nil until the virgin request header is parsed or faked.
86 /// Starts as a virgin request; see initRequest().
87 /// Adaptation and redirections replace it; see resetRequest().
88 HttpRequest * const request;
89
90 /// Usually starts as a URI received from the client, with scheme and host
91 /// added if needed. Is used to create the virgin request for initRequest().
92 /// URIs of adapted/redirected requests replace it via resetRequest().
93 char *uri;
94
95 // TODO: remove this field and store the URI directly in al->url
96 /// Cleaned up URI of the current (virgin or adapted/redirected) request,
97 /// computed URI of an internally-generated requests, or
98 /// one of the hard-coded "error:..." URIs.
99 char * const log_uri;
100
101 String store_id; /* StoreID for transactions where the request member is nil */
102
103 struct Out {
104 Out() : offset(0), size(0), headers_sz(0) {}
105
106 /// Roughly speaking, this offset points to the next body byte we want
107 /// to receive from Store. Without Ranges (and I/O errors), we should
108 /// have received (and written to the client) all the previous bytes.
109 /// XXX: The offset is updated by various receive-write steps, making
110 /// its exact meaning illusive. Its Out class placement is confusing.
111 int64_t offset;
112 /// Response header and body bytes written to the client connection.
113 uint64_t size;
114 /// Response header bytes written to the client connection.
115 /// Not to be confused with clientReplyContext::headers_sz.
116 size_t headers_sz;
117 } out;
118
119 HttpHdrRangeIter range_iter; /* data for iterating thru range specs */
120 size_t req_sz; /* raw request size on input, not current request size */
121
122 /// the processing tags associated with this request transaction.
123 // NP: still an enum so each stage altering it must take care when replacing it.
124 LogTags logType;
125
126 AccessLogEntry::Pointer al; ///< access.log entry
127
128 struct Flags {
129 Flags() : accel(false), internal(false), done_copying(false) {}
130
131 bool accel;
132 bool internal;
133 bool done_copying;
134 } flags;
135
136 struct Redirect {
137 Redirect() : status(Http::scNone), location(NULL) {}
138
139 Http::StatusCode status;
140 char *location;
141 } redirect;
142
143 dlink_node active;
144 dlink_list client_stream;
145 int64_t mRangeCLen() const;
146
147 ClientRequestContext *calloutContext;
148 void doCallouts();
149
150 // The three methods below prepare log_uri and friends for future logging.
151 // Call the best-fit method whenever the current request or its URI changes.
152
153 /// sets log_uri when we know the current request
154 void setLogUriToRequestUri();
155 /// sets log_uri to a parsed request URI when Squid fails to parse or
156 /// validate other request components, yielding no current request
157 void setLogUriToRawUri(const char *rawUri, const HttpRequestMethod &);
158 /// sets log_uri and uri to an internally-generated "error:..." URI when
159 /// neither the current request nor the parsed request URI are known
160 void setErrorUri(const char *errorUri);
161
162 /// Prepares to satisfy a Range request with a generated HTTP 206 response.
163 /// Initializes range_iter state to allow raw range_iter access.
164 /// \returns Content-Length value for the future response; never negative
165 int64_t prepPartialResponseGeneration();
166
167 /// Build an error reply. For use with the callouts.
168 void calloutsError(const err_type error, const ErrorDetail::Pointer &errDetail);
169
170 /// if necessary, stores new error information (if any)
171 void updateError(const Error &error);
172
173 #if USE_ADAPTATION
174 // AsyncJob virtual methods
175 virtual bool doneAll() const {
176 return Initiator::doneAll() &&
177 BodyConsumer::doneAll() && false;
178 }
179 virtual void callException(const std::exception &ex);
180 #endif
181
182 private:
183 /// assigns log_uri with aUri without copying the entire C-string
184 void absorbLogUri(char *aUri);
185 /// resets the current request and log_uri to nil
186 void clearRequest();
187 /// initializes the current unassigned request to the virgin request
188 /// sets the current request, asserting that it was unset
189 void assignRequest(HttpRequest *aRequest);
190
191 int64_t maxReplyBodySize_;
192 StoreEntry *entry_;
193 StoreEntry *loggingEntry_;
194 ConnStateData * conn_;
195
196 #if USE_OPENSSL
197 /// whether (and how) the request needs to be bumped
198 Ssl::BumpMode sslBumpNeed_;
199
200 public:
201 /// returns raw sslBump mode value
202 Ssl::BumpMode sslBumpNeed() const { return sslBumpNeed_; }
203 /// returns true if and only if the request needs to be bumped
204 bool sslBumpNeeded() const { return sslBumpNeed_ == Ssl::bumpServerFirst || sslBumpNeed_ == Ssl::bumpClientFirst || sslBumpNeed_ == Ssl::bumpBump || sslBumpNeed_ == Ssl::bumpPeek || sslBumpNeed_ == Ssl::bumpStare; }
205 /// set the sslBumpNeeded state
206 void sslBumpNeed(Ssl::BumpMode mode);
207 void sslBumpStart();
208 void sslBumpEstablish(Comm::Flag errflag);
209 #endif
210
211 #if USE_ADAPTATION
212
213 public:
214 void startAdaptation(const Adaptation::ServiceGroupPointer &g);
215 bool requestSatisfactionMode() const { return request_satisfaction_mode; }
216
217 private:
218 /// Handles an adaptation client request failure.
219 /// Bypasses the error if possible, or build an error reply.
220 void handleAdaptationFailure(const ErrorDetail::Pointer &errDetail, bool bypassable = false);
221
222 // Adaptation::Initiator API
223 virtual void noteAdaptationAnswer(const Adaptation::Answer &answer);
224 void handleAdaptedHeader(Http::Message *msg);
225 void handleAdaptationBlock(const Adaptation::Answer &answer);
226 virtual void noteAdaptationAclCheckDone(Adaptation::ServiceGroupPointer group);
227
228 // BodyConsumer API, called by BodyPipe
229 virtual void noteMoreBodyDataAvailable(BodyPipe::Pointer);
230 virtual void noteBodyProductionEnded(BodyPipe::Pointer);
231 virtual void noteBodyProducerAborted(BodyPipe::Pointer);
232
233 void endRequestSatisfaction();
234 /// called by StoreEntry when it has more buffer space available
235 void resumeBodyStorage();
236
237 private:
238 CbcPointer<Adaptation::Initiate> virginHeadSource;
239 BodyPipe::Pointer adaptedBodySource;
240
241 bool request_satisfaction_mode;
242 int64_t request_satisfaction_offset;
243 #endif
244 };
245
246 /* client http based routines */
247 char *clientConstructTraceEcho(ClientHttpRequest *);
248
249 ACLFilledChecklist *clientAclChecklistCreate(const acl_access * acl,ClientHttpRequest * http);
250 void clientAclChecklistFill(ACLFilledChecklist &, ClientHttpRequest *);
251 int clientHttpRequestStatus(int fd, ClientHttpRequest const *http);
252 void clientAccessCheck(ClientHttpRequest *);
253
254 /* ones that should be elsewhere */
255 void tunnelStart(ClientHttpRequest *);
256
257 #endif /* SQUID_CLIENTSIDEREQUEST_H */
258