]> git.ipfire.org Git - thirdparty/squid.git/blame - src/wais.cc
Summary: Final MSVC fixups.
[thirdparty/squid.git] / src / wais.cc
CommitLineData
f900607e 1
30a4f2a8 2/*
190154cf 3 * $Id: wais.cc,v 1.150 2003/08/10 11:00:45 robertc Exp $
30a4f2a8 4 *
5 * DEBUG: section 24 WAIS Relay
6 * AUTHOR: Harvest Derived
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
30a4f2a8 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
7528fc90 34 */
44a47c6e 35
36#include "squid.h"
e6ccf245 37#include "Store.h"
528b2c61 38#include "HttpRequest.h"
b67e2c8c 39#if DELAY_POOLS
40#include "DelayPools.h"
86a2f789 41#include "MemObject.h"
b67e2c8c 42#endif
a46d2c0e 43#include "comm.h"
ed43818f 44
62e76326 45class WaisStateData
46{
47
528b2c61 48public:
30a4f2a8 49 int fd;
090089c4 50 StoreEntry *entry;
7111c86a 51 method_t method;
2246b732 52 const HttpHeader *request_hdr;
cadc5bae 53 char url[MAX_URL];
190154cf 54 HttpRequest *request;
db1cd23c 55 FwdState *fwd;
528b2c61 56 char buf[BUFSIZ];
57 bool dataWritten;
58};
30a4f2a8 59
582b6456 60static PF waisStateFree;
5c5783a2 61static PF waisTimeout;
c4b7a5a9 62static IOCB waisReadReply;
f17936ab 63static CWCB waisSendComplete;
582b6456 64static PF waisSendRequest;
090089c4 65
582b6456 66static void
79d39a72 67waisStateFree(int fdnotused, void *data)
ba718c8f 68{
e6ccf245 69 WaisStateData *waisState = (WaisStateData *)data;
62e76326 70
51fa90db 71 if (waisState == NULL)
62e76326 72 return;
73
f88211e8 74 storeUnlockObject(waisState->entry);
62e76326 75
cadc5bae 76 requestUnlink(waisState->request);
62e76326 77
7dd44885 78 cbdataFree(waisState);
ba718c8f 79}
80
090089c4 81/* This will be called when socket lifetime is expired. */
b8d8561b 82static void
5c5783a2 83waisTimeout(int fd, void *data)
090089c4 84{
e6ccf245 85 WaisStateData *waisState = (WaisStateData *)data;
582b6456 86 StoreEntry *entry = waisState->entry;
9fb13bb6 87 debug(24, 4) ("waisTimeout: FD %d: '%s'\n", fd, storeUrl(entry));
62e76326 88
e3dd531e 89 if (entry->store_status == STORE_PENDING) {
62e76326 90 if (!waisState->dataWritten) {
91 fwdFail(waisState->fwd,
92 errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
93 }
e3dd531e 94 }
62e76326 95
51fa90db 96 comm_close(fd);
090089c4 97}
98
090089c4 99/* This will be called when data is ready to be read from fd. Read until
100 * error or connection closed. */
b8d8561b 101static void
c4b7a5a9 102waisReadReply(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
090089c4 103{
e6ccf245 104 WaisStateData *waisState = (WaisStateData *)data;
582b6456 105 StoreEntry *entry = waisState->entry;
56fa4cad 106 int clen;
56fa4cad 107 int bin;
447e176b 108 size_t read_sz;
109#if DELAY_POOLS
62e76326 110
b67e2c8c 111 DelayId delayId = entry->mem_obj->mostBytesAllowed();
447e176b 112#endif
c4b7a5a9 113
114 /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
62e76326 115
c4b7a5a9 116 if (flag == COMM_ERR_CLOSING) {
117 return;
118 }
119
e92e4e44 120 if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
62e76326 121 comm_close(fd);
122 return;
e92e4e44 123 }
62e76326 124
447e176b 125 errno = 0;
c4b7a5a9 126 read_sz = BUFSIZ;
62e76326 127
c4b7a5a9 128 if (flag == COMM_OK && len > 0) {
447e176b 129#if DELAY_POOLS
62e76326 130 delayId.bytesIn(len);
447e176b 131#endif
62e76326 132
133 kb_incr(&statCounter.server.all.kbytes_in, len);
134 kb_incr(&statCounter.server.other.kbytes_in, len);
ee1679df 135 }
62e76326 136
c4b7a5a9 137#if DELAY_POOLS
b67e2c8c 138 read_sz = delayId.bytesWanted(1, read_sz);
62e76326 139
c4b7a5a9 140#endif
62e76326 141
c4b7a5a9 142 debug(24, 5) ("waisReadReply: FD %d read len:%d\n", fd, (int)len);
62e76326 143
c4b7a5a9 144 if (flag == COMM_OK && len > 0) {
62e76326 145 commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
146 IOStats.Wais.reads++;
147
148 for (clen = len - 1, bin = 0; clen; bin++)
149 clen >>= 1;
150
151 IOStats.Wais.read_hist[bin]++;
56fa4cad 152 }
62e76326 153
c4b7a5a9 154 if (flag != COMM_OK || len < 0) {
62e76326 155 debug(50, 1) ("waisReadReply: FD %d: read failure: %s.\n",
156 fd, xstrerror());
157
158 if (ignoreErrno(xerrno)) {
159 /* reinstall handlers */
160 /* XXX This may loop forever */
c4b7a5a9 161 comm_read(fd, waisState->buf, read_sz, waisReadReply, waisState);
62e76326 162 } else {
163 ErrorState *err;
164 EBIT_CLR(entry->flags, ENTRY_CACHABLE);
165 storeReleaseRequest(entry);
166 err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
167 err->xerrno = errno;
168 err->request = requestLink(waisState->request);
169 errorAppendEntry(entry, err);
170 comm_close(fd);
171 }
528b2c61 172 } else if (flag == COMM_OK && len == 0 && !waisState->dataWritten) {
62e76326 173 ErrorState *err;
174 err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
175 err->xerrno = errno;
176 err->request = requestLink(waisState->request);
177 errorAppendEntry(entry, err);
178 comm_close(fd);
c4b7a5a9 179 } else if (flag == COMM_OK && len == 0) {
62e76326 180 /* Connection closed; retrieval done. */
181 entry->expires = squid_curtime;
182 fwdComplete(waisState->fwd);
183 comm_close(fd);
090089c4 184 } else {
62e76326 185 waisState->dataWritten = 1;
186 storeAppend(entry, buf, len);
c4b7a5a9 187 comm_read(fd, waisState->buf, read_sz, waisReadReply, waisState);
090089c4 188 }
189}
190
191/* This will be called when request write is complete. Schedule read of
192 * reply. */
b8d8561b 193static void
3d7e9d7c 194waisSendComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag, void *data)
090089c4 195{
e6ccf245 196 WaisStateData *waisState = (WaisStateData *)data;
582b6456 197 StoreEntry *entry = waisState->entry;
a3d5953d 198 debug(24, 5) ("waisSendComplete: FD %d size: %d errflag: %d\n",
62e76326 199 fd, (int) size, errflag);
200
ee1679df 201 if (size > 0) {
62e76326 202 fd_bytes(fd, size, FD_WRITE);
203 kb_incr(&statCounter.server.all.kbytes_out, size);
204 kb_incr(&statCounter.server.other.kbytes_out, size);
ee1679df 205 }
62e76326 206
ea3a2a69 207 if (errflag == COMM_ERR_CLOSING)
62e76326 208 return;
209
090089c4 210 if (errflag) {
62e76326 211 ErrorState *err;
212 err = errorCon(ERR_WRITE_ERROR, HTTP_SERVICE_UNAVAILABLE);
213 err->xerrno = errno;
214 err->request = requestLink(waisState->request);
215 errorAppendEntry(entry, err);
216 comm_close(fd);
090089c4 217 } else {
62e76326 218 /* Schedule read reply. */
a46d2c0e 219 entry->delayAwareRead(fd, waisState->buf, BUFSIZ, waisReadReply, waisState);
090089c4 220 }
090089c4 221}
222
223/* This will be called when connect completes. Write request. */
b8d8561b 224static void
582b6456 225waisSendRequest(int fd, void *data)
090089c4 226{
e6ccf245 227 WaisStateData *waisState = (WaisStateData *)data;
2246b732 228 MemBuf mb;
0ee4272b 229 const char *Method = RequestMethodStr[waisState->method];
a3d5953d 230 debug(24, 5) ("waisSendRequest: FD %d\n", fd);
4d62b0af 231 memBufDefInit(&mb);
232 memBufPrintf(&mb, "%s %s HTTP/1.0\r\n", Method, waisState->url);
62e76326 233
2246b732 234 if (waisState->request_hdr) {
62e76326 235 Packer p;
236 packerToMemInit(&p, &mb);
237 httpHeaderPackInto(waisState->request_hdr, &p);
238 packerClean(&p);
2246b732 239 }
62e76326 240
2246b732 241 memBufPrintf(&mb, "\r\n");
242 debug(24, 6) ("waisSendRequest: buf: %s\n", mb.buf);
d4cb310b 243 comm_old_write_mbuf(fd, mb, waisSendComplete, waisState);
62e76326 244
d46a87a8 245 if (EBIT_TEST(waisState->entry->flags, ENTRY_CACHABLE))
62e76326 246 storeSetPublicKey(waisState->entry); /* Make it public */
247
ec250dfd 248 EBIT_CLR(waisState->entry->flags, ENTRY_FWD_HDR_WAIT);
30a4f2a8 249}
250
28c60158 251CBDATA_TYPE(WaisStateData);
770f051d 252void
db1cd23c 253waisStart(FwdState * fwd)
090089c4 254{
30a4f2a8 255 WaisStateData *waisState = NULL;
190154cf 256 HttpRequest *request = fwd->request;
db1cd23c 257 StoreEntry *entry = fwd->entry;
258 int fd = fwd->server_fd;
9fb13bb6 259 const char *url = storeUrl(entry);
f182d1c5 260 method_t method = request->method;
a3d5953d 261 debug(24, 3) ("waisStart: \"%s %s\"\n", RequestMethodStr[method], url);
83704487 262 statCounter.server.all.requests++;
263 statCounter.server.other.requests++;
28c60158 264 CBDATA_INIT_TYPE(WaisStateData);
72711e31 265 waisState = cbdataAlloc(WaisStateData);
30a4f2a8 266 waisState->method = method;
2246b732 267 waisState->request_hdr = &request->header;
30a4f2a8 268 waisState->fd = fd;
0a0bf5db 269 waisState->entry = entry;
528b2c61 270 waisState->dataWritten = 0;
cadc5bae 271 xstrncpy(waisState->url, url, MAX_URL);
272 waisState->request = requestLink(request);
db1cd23c 273 waisState->fwd = fwd;
bfcaf585 274 comm_add_close_handler(waisState->fd, waisStateFree, waisState);
770f051d 275 storeLockObject(entry);
41462d93 276 commSetTimeout(fd, Config.Timeout.read, waisTimeout, waisState);
c4b7a5a9 277 waisSendRequest(fd, waisState);
090089c4 278}