]>
Commit | Line | Data |
---|---|---|
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 | ||
a553a5a3 | 36 | #include "comm.h" |
0655fa4d | 37 | #include "StoreIOBuffer.h" |
5f8252d2 | 38 | #include "BodyPipe.h" |
a2ac85d9 | 39 | #include "RefCount.h" |
1cf238db | 40 | #include "ICAP/AsyncJob.h" |
41 | #include "CommCalls.h" | |
0655fa4d | 42 | |
43 | class ConnStateData; | |
44 | ||
45 | class ClientHttpRequest; | |
46 | ||
47 | class clientStreamNode; | |
48 | ||
9554bbf2 | 49 | class AuthUserRequest; |
50 | ||
2512d159 | 51 | template <class T> |
2512d159 | 52 | class Range; |
53 | ||
0655fa4d | 54 | class ClientSocketContext : public RefCountable |
55 | { | |
56 | ||
57 | public: | |
58 | typedef RefCount<ClientSocketContext> Pointer; | |
59 | void *operator new(size_t); | |
60 | void operator delete(void *); | |
0655fa4d | 61 | ClientSocketContext(); |
62 | ~ClientSocketContext(); | |
63 | bool startOfOutput() const; | |
64 | void writeComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag); | |
65 | void keepaliveNextRequest(); | |
66 | ClientHttpRequest *http; /* we own this */ | |
fedd1531 | 67 | HttpReply *reply; |
0655fa4d | 68 | char reqbuf[HTTP_REQBUF_SZ]; |
69 | Pointer next; | |
70 | ||
9e008dda | 71 | struct { |
0655fa4d | 72 | |
9e008dda | 73 | unsigned deferred:1; /* This is a pipelined request waiting for the current object to complete */ |
0655fa4d | 74 | |
9e008dda | 75 | unsigned parsed_ok:1; /* Was this parsed correctly? */ |
2fadd50d | 76 | } flags; |
0655fa4d | 77 | bool mayUseConnection() const {return mayUseConnection_;} |
78 | ||
9e008dda | 79 | void mayUseConnection(bool aBool) { |
0655fa4d | 80 | mayUseConnection_ = aBool; |
81 | debug (33,3)("ClientSocketContext::mayUseConnection: This %p marked %d\n", | |
82 | this, aBool); | |
83 | } | |
84 | ||
7d9b0628 | 85 | class DeferredParams |
0655fa4d | 86 | { |
7d9b0628 | 87 | |
88 | public: | |
0655fa4d | 89 | clientStreamNode *node; |
90 | HttpReply *rep; | |
91 | StoreIOBuffer queuedBuffer; | |
7d9b0628 | 92 | }; |
0655fa4d | 93 | |
7d9b0628 | 94 | DeferredParams deferredparams; |
57d55dfa | 95 | int64_t writtenToSocket; |
0655fa4d | 96 | void pullData(); |
47f6e231 | 97 | int64_t getNextRangeOffset() const; |
0655fa4d | 98 | bool canPackMoreRanges() const; |
99 | clientStream_status_t socketState(); | |
100 | void sendBody(HttpReply * rep, StoreIOBuffer bodyData); | |
101 | void sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData); | |
47f6e231 | 102 | size_t lengthToSend(Range<int64_t> const &available); |
0655fa4d | 103 | void noteSentBodyBytes(size_t); |
104 | void buildRangeHeader(HttpReply * rep); | |
105 | int fd() const; | |
106 | clientStreamNode * getTail() const; | |
107 | clientStreamNode * getClientReplyContext() const; | |
108 | void connIsFinished(); | |
1cf238db | 109 | void removeFromConnectionList(ConnStateData * conn); |
2324cda2 | 110 | void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer receivedData); |
0655fa4d | 111 | bool multipartRangeRequest() const; |
0655fa4d | 112 | void registerWithConn(); |
113 | ||
114 | private: | |
115 | CBDATA_CLASS(ClientSocketContext); | |
116 | void prepareReply(HttpReply * rep); | |
2512d159 | 117 | void packRange(StoreIOBuffer const &, MemBuf * mb); |
0655fa4d | 118 | void deRegisterWithConn(); |
55e44db9 | 119 | void doClose(); |
5f8252d2 | 120 | void initiateClose(const char *reason); |
0655fa4d | 121 | bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */ |
122 | bool connRegistered_; | |
123 | }; | |
124 | ||
63be0a78 | 125 | /** A connection to a socket */ |
1cf238db | 126 | class ConnStateData : public BodyProducer/*, public RefCountable*/ |
6039b729 | 127 | { |
128 | ||
129 | public: | |
6039b729 | 130 | |
131 | ConnStateData(); | |
132 | ~ConnStateData(); | |
133 | ||
134 | void readSomeData(); | |
135 | int getAvailableBufferLength() const; | |
136 | bool areAllContextsForThisConnection() const; | |
137 | void freeAllContexts(); | |
138 | void readNextRequest(); | |
139 | void makeSpaceAvailable(); | |
0655fa4d | 140 | ClientSocketContext::Pointer getCurrentContext() const; |
141 | void addContextToQueue(ClientSocketContext * context); | |
142 | int getConcurrentRequestCount() const; | |
a2ac85d9 | 143 | bool isOpen() const; |
6039b729 | 144 | |
145 | int fd; | |
146 | ||
9e008dda | 147 | struct In { |
6039b729 | 148 | In(); |
149 | ~In(); | |
150 | char *addressToReadInto() const; | |
151 | char *buf; | |
152 | size_t notYetUsed; | |
153 | size_t allocatedSize; | |
0b86805b | 154 | } in; |
6039b729 | 155 | |
3e62bd58 | 156 | int64_t bodySizeLeft(); |
3b299123 | 157 | |
63be0a78 | 158 | /** |
3b299123 | 159 | * Is this connection based authentication? if so what type it |
160 | * is. | |
161 | */ | |
162 | auth_type_t auth_type; | |
63be0a78 | 163 | |
164 | /** | |
3b299123 | 165 | * note this is ONLY connection based because NTLM is against HTTP spec. |
166 | * the user details for connection based authentication | |
167 | */ | |
76f142cd | 168 | AuthUserRequest *auth_user_request; |
63be0a78 | 169 | |
170 | /** | |
3b299123 | 171 | * used by the owner of the connection, opaque otherwise |
172 | * TODO: generalise the connection owner concept. | |
173 | */ | |
174 | ClientSocketContext::Pointer currentobject; | |
6039b729 | 175 | |
ad61a2b4 | 176 | IpAddress peer; |
6039b729 | 177 | |
ad61a2b4 | 178 | IpAddress me; |
6039b729 | 179 | |
ad61a2b4 | 180 | IpAddress log_addr; |
6039b729 | 181 | char rfc931[USER_IDENT_SZ]; |
182 | int nrequests; | |
183 | ||
9e008dda | 184 | struct { |
48962ba8 | 185 | bool readMoreRequests; |
6e1d409c | 186 | bool swanSang; // XXX: temporary flag to check proper cleanup |
2fadd50d | 187 | } flags; |
d67acb4e AJ |
188 | struct { |
189 | int fd; /* pinned server side connection */ | |
190 | char *host; /* host name of pinned connection */ | |
191 | int port; /* port of pinned connection */ | |
192 | bool pinned; /* this connection was pinned */ | |
193 | bool auth; /* pinned for www authentication */ | |
194 | struct peer *peer; /* peer the connection goes via */ | |
9e008dda AJ |
195 | AsyncCall::Pointer closeHandler; /*The close handler for pinned server side connection*/ |
196 | } pinning; | |
d67acb4e | 197 | |
6039b729 | 198 | http_port_list *port; |
199 | ||
200 | bool transparent() const; | |
201 | void transparent(bool const); | |
202 | bool reading() const; | |
203 | void reading(bool const); | |
5f8252d2 | 204 | |
55e44db9 | 205 | bool closing() const; |
5f8252d2 | 206 | void startClosing(const char *reason); |
6039b729 | 207 | |
3e62bd58 | 208 | BodyPipe::Pointer expectRequestBody(int64_t size); |
1cf238db | 209 | virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer); |
210 | virtual void noteBodyConsumerAborted(BodyPipe::Pointer); | |
5f8252d2 | 211 | |
212 | void handleReadData(char *buf, size_t size); | |
213 | void handleRequestBodyData(); | |
0b86805b | 214 | |
d67acb4e AJ |
215 | /** |
216 | * Correlate the current ConnStateData object with the pinning_fd socket descriptor. | |
217 | */ | |
218 | void pinConnection(int fd, HttpRequest *request, struct peer *peer, bool auth); | |
219 | /** | |
220 | * Decorrelate the ConnStateData object from its pinned peer | |
221 | */ | |
9e008dda | 222 | void unpinConnection(); |
d67acb4e AJ |
223 | /** |
224 | * Checks if there is pinning info if it is valid. It can close the server side connection | |
225 | * if pinned info is not valid. | |
226 | \param request if it is not NULL also checks if the pinning info refers to the request client side HttpRequest | |
227 | \param peer if it is not NULL also check if the peer is the pinning peer | |
228 | \return The fd of the server side connection or -1 if fails. | |
229 | */ | |
230 | int validatePinnedConnection(HttpRequest *request, const struct peer *peer=NULL); | |
231 | /** | |
232 | * returts the pinned peer if exists, NULL otherwise | |
233 | */ | |
234 | struct peer *pinnedPeer() const {return pinning.peer;} | |
235 | bool pinnedAuth() const {return pinning.auth;} | |
236 | ||
237 | // pining related comm callbacks | |
238 | void clientPinnedConnectionClosed(const CommCloseCbParams &io); | |
239 | ||
1cf238db | 240 | // comm callbacks |
241 | void clientReadRequest(const CommIoCbParams &io); | |
242 | void connStateClosed(const CommCloseCbParams &io); | |
243 | void requestTimeout(const CommTimeoutCbParams ¶ms); | |
244 | ||
245 | // AsyncJob API | |
246 | virtual bool doneAll() const { return BodyProducer::doneAll() && false;} | |
6e1d409c | 247 | virtual void swanSong(); |
1cf238db | 248 | |
ae7ff0b8 | 249 | #if USE_SSL |
250 | bool switchToHttps(); | |
251 | bool switchedToHttps() const { return switchedToHttps_; } | |
252 | #else | |
253 | bool switchedToHttps() const { return false; } | |
254 | #endif | |
255 | ||
1cf238db | 256 | private: |
257 | int connReadWasError(comm_err_t flag, int size, int xerrno); | |
258 | int connFinishedWithConn(int size); | |
259 | void clientMaybeReadData(int do_next_read); | |
260 | void clientAfterReadingRequests(int do_next_read); | |
261 | ||
6039b729 | 262 | private: |
0b86805b | 263 | CBDATA_CLASS2(ConnStateData); |
6039b729 | 264 | bool transparent_; |
265 | bool reading_; | |
55e44db9 | 266 | bool closing_; |
1cf238db | 267 | |
ae7ff0b8 | 268 | bool switchedToHttps_; |
5f8252d2 | 269 | BodyPipe::Pointer bodyPipe; // set when we are reading request body |
6039b729 | 270 | }; |
271 | ||
55e44db9 | 272 | /* convenience class while splitting up body handling */ |
273 | /* temporary existence only - on stack use expected */ | |
274 | ||
de31d06f | 275 | void setLogUri(ClientHttpRequest * http, char const *uri); |
276 | ||
8596962e | 277 | const char *findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end = NULL); |
278 | ||
6039b729 | 279 | #endif /* SQUID_CLIENTSIDE_H */ |