]> git.ipfire.org Git - thirdparty/squid.git/blame - src/client_side.h
Polished names, comments, and code formatting.
[thirdparty/squid.git] / src / client_side.h
CommitLineData
6039b729 1/*
262a0e14 2 * $Id$
6039b729 3 *
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
9e008dda 21 *
6039b729 22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
9e008dda 26 *
6039b729 27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 */
32
33#ifndef SQUID_CLIENTSIDE_H
34#define SQUID_CLIENTSIDE_H
35
2f1431ea 36#if USE_AUTH
a33a428a 37#include "auth/UserRequest.h"
2f1431ea 38#endif
d1e045c3 39#include "base/AsyncJob.h"
a98c2da5
AJ
40#include "BodyPipe.h"
41#include "comm.h"
1cf238db 42#include "CommCalls.h"
655daa06 43#include "HttpControlMsg.h"
4c14658e 44#include "HttpParser.h"
a98c2da5
AJ
45#include "RefCount.h"
46#include "StoreIOBuffer.h"
061bbdec
CT
47#if USE_SSL
48#include "ssl/support.h"
49#endif
0655fa4d 50
51class ConnStateData;
0655fa4d 52class ClientHttpRequest;
0655fa4d 53class clientStreamNode;
3ff65596 54class ChunkedCodingParser;
3ff65596 55
27774cee
AJ
56/**
57 * Badly named.
58 * This is in fact the processing context for a single HTTP request.
59 *
60 * Managing what has been done, and what happens next to the data buffer
61 * holding what we hope is an HTTP request.
62 *
63 * Parsing is still a mess of global functions done in conjunction with the
64 * real socket controller which generated ClientHttpRequest.
65 * It also generates one of us and passes us control from there based on
66 * the results of the parse.
67 *
68 * After that all the request interpretation and adaptation is in our scope.
69 * Then finally the reply fetcher is created by this and we get the result
70 * back. Which we then have to manage writing of it to the ConnStateData.
71 *
72 * The socket level management is done by a ConnStateData which owns us.
73 * The scope of this objects control over a socket consists of the data
74 * buffer received from ConnStateData with an initially unknown length.
75 * When that length is known it sets the end bounary of our acces to the
76 * buffer.
77 *
78 * The individual processing actions are done by other Jobs which we
79 * kick off as needed.
80 */
0655fa4d 81class ClientSocketContext : public RefCountable
82{
83
84public:
85 typedef RefCount<ClientSocketContext> Pointer;
86 void *operator new(size_t);
87 void operator delete(void *);
0655fa4d 88 ClientSocketContext();
89 ~ClientSocketContext();
90 bool startOfOutput() const;
e0d28505 91 void writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag);
0655fa4d 92 void keepaliveNextRequest();
be364179
AJ
93
94 Comm::ConnectionPointer clientConnection; /// details about the client connection socket.
0655fa4d 95 ClientHttpRequest *http; /* we own this */
fedd1531 96 HttpReply *reply;
0655fa4d 97 char reqbuf[HTTP_REQBUF_SZ];
98 Pointer next;
99
9e008dda 100 struct {
0655fa4d 101
9e008dda 102 unsigned deferred:1; /* This is a pipelined request waiting for the current object to complete */
0655fa4d 103
9e008dda 104 unsigned parsed_ok:1; /* Was this parsed correctly? */
2fadd50d 105 } flags;
0655fa4d 106 bool mayUseConnection() const {return mayUseConnection_;}
107
9e008dda 108 void mayUseConnection(bool aBool) {
0655fa4d 109 mayUseConnection_ = aBool;
96e03dd8 110 debugs(33,3, HERE << "This " << this << " marked " << aBool);
0655fa4d 111 }
112
7d9b0628 113 class DeferredParams
0655fa4d 114 {
7d9b0628 115
116 public:
0655fa4d 117 clientStreamNode *node;
118 HttpReply *rep;
119 StoreIOBuffer queuedBuffer;
7d9b0628 120 };
0655fa4d 121
7d9b0628 122 DeferredParams deferredparams;
57d55dfa 123 int64_t writtenToSocket;
0655fa4d 124 void pullData();
47f6e231 125 int64_t getNextRangeOffset() const;
0655fa4d 126 bool canPackMoreRanges() const;
127 clientStream_status_t socketState();
128 void sendBody(HttpReply * rep, StoreIOBuffer bodyData);
129 void sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData);
47f6e231 130 size_t lengthToSend(Range<int64_t> const &available);
0655fa4d 131 void noteSentBodyBytes(size_t);
132 void buildRangeHeader(HttpReply * rep);
0655fa4d 133 clientStreamNode * getTail() const;
134 clientStreamNode * getClientReplyContext() const;
135 void connIsFinished();
1cf238db 136 void removeFromConnectionList(ConnStateData * conn);
2324cda2 137 void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer receivedData);
0655fa4d 138 bool multipartRangeRequest() const;
0655fa4d 139 void registerWithConn();
f692498b 140 void noteIoError(const int xerrno); ///< update state to reflect I/O error
0655fa4d 141
655daa06
AR
142 /// starts writing 1xx control message to the client
143 void writeControlMsg(HttpControlMsg &msg);
144
145protected:
1b76e6c1 146 static IOCB WroteControlMsg;
e0d28505 147 void wroteControlMsg(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag, int xerrno);
655daa06 148
0655fa4d 149private:
150 CBDATA_CLASS(ClientSocketContext);
151 void prepareReply(HttpReply * rep);
4ad60609 152 void packChunk(const StoreIOBuffer &bodyData, MemBuf &mb);
2512d159 153 void packRange(StoreIOBuffer const &, MemBuf * mb);
0655fa4d 154 void deRegisterWithConn();
55e44db9 155 void doClose();
5f8252d2 156 void initiateClose(const char *reason);
655daa06
AR
157
158 AsyncCall::Pointer cbControlMsgSent; ///< notifies HttpControlMsg Source
159
0655fa4d 160 bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */
161 bool connRegistered_;
162};
163
a98c2da5
AJ
164
165class ConnectionDetail;
061bbdec
CT
166#if USE_SSL
167namespace Ssl {
fd4624d7 168 class ServerBump;
061bbdec
CT
169}
170#endif
27774cee
AJ
171/**
172 * Manages a connection to a client.
173 *
174 * Multiple requests (up to 2) can be pipelined. This object is responsible for managing
175 * which one is currently being fulfilled and what happens to the queue if the current one
176 * causes the client connection to be closed early.
177 *
178 * Act as a manager for the connection and passes data in buffer to the current parser.
179 * the parser has ambiguous scope at present due to being made from global functions
180 * I believe this object uses the parser to identify boundaries and kick off the
181 * actual HTTP request handling objects (ClientSocketContext, ClientHttpRequest, HttpRequest)
182 *
183 * If the above can be confirmed accurate we can call this object PipelineManager or similar
184 */
655daa06 185class ConnStateData : public BodyProducer, public HttpControlMsgSink
6039b729 186{
187
188public:
6039b729 189
190 ConnStateData();
191 ~ConnStateData();
192
193 void readSomeData();
194 int getAvailableBufferLength() const;
195 bool areAllContextsForThisConnection() const;
196 void freeAllContexts();
f692498b 197 void notifyAllContexts(const int xerrno); ///< tell everybody about the err
4959e21e 198 /// Traffic parsing
f35961af 199 bool clientParseRequests();
6039b729 200 void readNextRequest();
1368d115 201 bool maybeMakeSpaceAvailable();
0655fa4d 202 ClientSocketContext::Pointer getCurrentContext() const;
203 void addContextToQueue(ClientSocketContext * context);
204 int getConcurrentRequestCount() const;
a2ac85d9 205 bool isOpen() const;
39cb8c41 206 void checkHeaderLimits();
6039b729 207
655daa06
AR
208 // HttpControlMsgSink API
209 virtual void sendControlMsg(HttpControlMsg msg);
6039b729 210
5c336a3b 211 // Client TCP connection details from comm layer.
73c36fd9 212 Comm::ConnectionPointer clientConnection;
6039b729 213
9e008dda 214 struct In {
6039b729 215 In();
216 ~In();
217 char *addressToReadInto() const;
3ff65596 218
e1381638 219 ChunkedCodingParser *bodyParser; ///< parses chunked request body
6039b729 220 char *buf;
221 size_t notYetUsed;
222 size_t allocatedSize;
0b86805b 223 } in;
6039b729 224
39cb8c41
AR
225 /** number of body bytes we need to comm_read for the "current" request
226 *
227 * \retval 0 We do not need to read any [more] body bytes
228 * \retval negative May need more but do not know how many; could be zero!
229 * \retval positive Need to read exactly that many more body bytes
230 */
231 int64_t mayNeedToReadMoreBody() const;
3b299123 232
2f1431ea 233#if USE_AUTH
63be0a78 234 /**
a1ce83aa 235 * note this is ONLY connection based because NTLM and Negotiate is against HTTP spec.
3b299123 236 * the user details for connection based authentication
237 */
c7baff40 238 Auth::UserRequest::Pointer auth_user_request;
2f1431ea 239#endif
63be0a78 240
241 /**
3b299123 242 * used by the owner of the connection, opaque otherwise
243 * TODO: generalise the connection owner concept.
244 */
245 ClientSocketContext::Pointer currentobject;
6039b729 246
b7ac5457 247 Ip::Address log_addr;
6039b729 248 int nrequests;
249
9e008dda 250 struct {
f35961af 251 bool readMore; ///< needs comm_read (for this request or new requests)
6e1d409c 252 bool swanSang; // XXX: temporary flag to check proper cleanup
2fadd50d 253 } flags;
d67acb4e 254 struct {
73c36fd9 255 Comm::ConnectionPointer serverConnection; /* pinned server side connection */
d67acb4e
AJ
256 char *host; /* host name of pinned connection */
257 int port; /* port of pinned connection */
258 bool pinned; /* this connection was pinned */
259 bool auth; /* pinned for www authentication */
260 struct peer *peer; /* peer the connection goes via */
9e008dda
AJ
261 AsyncCall::Pointer closeHandler; /*The close handler for pinned server side connection*/
262 } pinning;
d67acb4e 263
65d448bc 264 AnyP::PortCfg *port;
6039b729 265
266 bool transparent() const;
6039b729 267 bool reading() const;
f84dd7eb 268 void stopReading(); ///< cancels comm_read if it is scheduled
5f8252d2 269
cf6eb29e
CT
270 /// true if we stopped receiving the request
271 const char *stoppedReceiving() const { return stoppedReceiving_; }
272 /// true if we stopped sending the response
273 const char *stoppedSending() const { return stoppedSending_; }
274 /// note request receiving error and close as soon as we write the response
275 void stopReceiving(const char *error);
276 /// note response sending error and close as soon as we read the request
277 void stopSending(const char *error);
278
eb44b2d7 279 void expectNoForwarding(); ///< cleans up virgin request [body] forwarding state
6039b729 280
3e62bd58 281 BodyPipe::Pointer expectRequestBody(int64_t size);
1cf238db 282 virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer);
283 virtual void noteBodyConsumerAborted(BodyPipe::Pointer);
5f8252d2 284
39cb8c41
AR
285 bool handleReadData(char *buf, size_t size);
286 bool handleRequestBodyData();
0b86805b 287
d67acb4e
AJ
288 /**
289 * Correlate the current ConnStateData object with the pinning_fd socket descriptor.
290 */
e3a4aecc 291 void pinConnection(const Comm::ConnectionPointer &pinServerConn, HttpRequest *request, struct peer *peer, bool auth);
d67acb4e
AJ
292 /**
293 * Decorrelate the ConnStateData object from its pinned peer
294 */
9e008dda 295 void unpinConnection();
d67acb4e
AJ
296 /**
297 * Checks if there is pinning info if it is valid. It can close the server side connection
298 * if pinned info is not valid.
299 \param request if it is not NULL also checks if the pinning info refers to the request client side HttpRequest
300 \param peer if it is not NULL also check if the peer is the pinning peer
e3a4aecc 301 \return The details of the server side connection (may be closed if failures were present).
d67acb4e 302 */
e3a4aecc 303 const Comm::ConnectionPointer validatePinnedConnection(HttpRequest *request, const struct peer *peer);
d67acb4e
AJ
304 /**
305 * returts the pinned peer if exists, NULL otherwise
306 */
307 struct peer *pinnedPeer() const {return pinning.peer;}
308 bool pinnedAuth() const {return pinning.auth;}
309
310 // pining related comm callbacks
311 void clientPinnedConnectionClosed(const CommCloseCbParams &io);
312
1cf238db 313 // comm callbacks
314 void clientReadRequest(const CommIoCbParams &io);
315 void connStateClosed(const CommCloseCbParams &io);
316 void requestTimeout(const CommTimeoutCbParams &params);
317
318 // AsyncJob API
319 virtual bool doneAll() const { return BodyProducer::doneAll() && false;}
6e1d409c 320 virtual void swanSong();
1cf238db 321
84c77748
AR
322 /// Changes state so that we close the connection and quit after serving
323 /// the client-side-detected error response instead of getting stuck.
324 void quitAfterError(HttpRequest *request); // meant to be private
325
ae7ff0b8 326#if USE_SSL
fd4624d7 327 /// called by FwdState when it is done bumping the server
d7ce0bcd
AR
328 void httpsPeeked(Comm::ConnectionPointer serverConnection);
329
95d2589c 330 /// Start to create dynamic SSL_CTX for host or uses static port SSL context.
1ce2822d 331 void getSslContextStart();
95d2589c
CT
332 /**
333 * Done create dynamic ssl certificate.
334 *
335 * \param[in] isNew if generated certificate is new, so we need to add this certificate to storage.
336 */
1ce2822d 337 void getSslContextDone(SSL_CTX * sslContext, bool isNew = false);
95d2589c
CT
338 /// Callback function. It is called when squid receive message from ssl_crtd.
339 static void sslCrtdHandleReplyWrapper(void *data, char *reply);
340 /// Proccess response from ssl_crtd.
341 void sslCrtdHandleReply(const char * reply);
342
caf3666d 343 void switchToHttps(HttpRequest *request, Ssl::BumpMode bumpServerMode);
ae7ff0b8 344 bool switchedToHttps() const { return switchedToHttps_; }
fd4624d7 345 Ssl::ServerBump *serverBump() {return sslServerBump;}
2bd84e5f 346 void setServerBump(Ssl::ServerBump *srvBump) {if (!sslServerBump) sslServerBump = srvBump;}
fb2178bb
CT
347 /// Fill the certAdaptParams with the required data for certificate adaptation
348 /// and create the key for storing/retrieve the certificate to/from the cache
06997a38 349 void buildSslCertGenerationParams(Ssl::CertificateProperties &certProperties);
7a957a93
AR
350 /// Called when the client sends the first request on a bumped connection.
351 /// Returns false if no [delayed] error should be written to the client.
352 /// Otherwise, writes the error to the client and returns true. Also checks
353 /// for SQUID_X509_V_ERR_DOMAIN_MISMATCH on bumped requests.
8eb0a7ee 354 bool serveDelayedError(ClientSocketContext *context);
ae7ff0b8 355#else
356 bool switchedToHttps() const { return false; }
357#endif
358
39cb8c41
AR
359protected:
360 void startDechunkingRequest();
361 void finishDechunkingRequest(bool withSuccess);
362 void abortChunkedRequestBody(const err_type error);
363 err_type handleChunkedRequestBody(size_t &putSize);
3ff65596 364
1cf238db 365private:
366 int connReadWasError(comm_err_t flag, int size, int xerrno);
367 int connFinishedWithConn(int size);
f35961af 368 void clientAfterReadingRequests();
1cf238db 369
6039b729 370private:
4959e21e 371 HttpParser parser_;
89aec9b6 372
4959e21e 373 // XXX: CBDATA plays with public/private and leaves the following 'private' fields all public... :(
0b86805b 374 CBDATA_CLASS2(ConnStateData);
1cf238db 375
d7ce0bcd 376#if USE_SSL
ae7ff0b8 377 bool switchedToHttps_;
fb2178bb
CT
378 /// The SSL server host name appears in CONNECT request or the server ip address for the intercepted requests
379 String sslConnectHostOrIp; ///< The SSL server host name as passed in the CONNECT request
380 String sslCommonName; ///< CN name for SSL certificate generation
381 String sslBumpCertKey; ///< Key to use to store/retrieve generated certificate
d7ce0bcd 382
fd4624d7
CT
383 /// HTTPS server cert. fetching state for bump-ssl-server-first
384 Ssl::ServerBump *sslServerBump;
aebe6888 385 Ssl::CertSignAlgorithm signAlgorithm; ///< The signing algorithm to use
d7ce0bcd
AR
386#endif
387
cf6eb29e
CT
388 /// the reason why we no longer write the response or nil
389 const char *stoppedSending_;
390 /// the reason why we no longer read the request or nil
391 const char *stoppedReceiving_;
392
f84dd7eb 393 AsyncCall::Pointer reader; ///< set when we are reading
5f8252d2 394 BodyPipe::Pointer bodyPipe; // set when we are reading request body
6039b729 395};
396
55e44db9 397/* convenience class while splitting up body handling */
398/* temporary existence only - on stack use expected */
399
727552f4 400void setLogUri(ClientHttpRequest * http, char const *uri, bool cleanUrl = false);
de31d06f 401
8596962e 402const char *findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end = NULL);
403
6039b729 404#endif /* SQUID_CLIENTSIDE_H */