]> git.ipfire.org Git - thirdparty/squid.git/blame - src/wais.cc
change CLIENT_ABORT_REQUEST into mem_obj->abort.callback()
[thirdparty/squid.git] / src / wais.cc
CommitLineData
f900607e 1
30a4f2a8 2/*
bfcaf585 3 * $Id: wais.cc,v 1.74 1997/06/02 05:39:51 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 24 WAIS Relay
6 * AUTHOR: Harvest Derived
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
30a4f2a8 9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
7528fc90 31
32/*
30a4f2a8 33 * Copyright (c) 1994, 1995. All rights reserved.
34 *
35 * The Harvest software was developed by the Internet Research Task
36 * Force Research Group on Resource Discovery (IRTF-RD):
37 *
38 * Mic Bowman of Transarc Corporation.
39 * Peter Danzig of the University of Southern California.
40 * Darren R. Hardy of the University of Colorado at Boulder.
41 * Udi Manber of the University of Arizona.
42 * Michael F. Schwartz of the University of Colorado at Boulder.
43 * Duane Wessels of the University of Colorado at Boulder.
44 *
45 * This copyright notice applies to software in the Harvest
46 * ``src/'' directory only. Users should consult the individual
47 * copyright notices in the ``components/'' subdirectories for
48 * copyright information about other software bundled with the
49 * Harvest source code distribution.
50 *
51 * TERMS OF USE
52 *
53 * The Harvest software may be used and re-distributed without
54 * charge, provided that the software origin and research team are
55 * cited in any use of the system. Most commonly this is
56 * accomplished by including a link to the Harvest Home Page
57 * (http://harvest.cs.colorado.edu/) from the query page of any
58 * Broker you deploy, as well as in the query result pages. These
59 * links are generated automatically by the standard Broker
60 * software distribution.
61 *
62 * The Harvest software is provided ``as is'', without express or
63 * implied warranty, and with no support nor obligation to assist
64 * in its use, correction, modification or enhancement. We assume
65 * no liability with respect to the infringement of copyrights,
66 * trade secrets, or any patents, and are not responsible for
67 * consequential damages. Proper use of the Harvest software is
68 * entirely the responsibility of the user.
69 *
70 * DERIVATIVE WORKS
71 *
72 * Users may make derivative works from the Harvest software, subject
73 * to the following constraints:
74 *
75 * - You must include the above copyright notice and these
76 * accompanying paragraphs in all forms of derivative works,
77 * and any documentation and other materials related to such
78 * distribution and use acknowledge that the software was
79 * developed at the above institutions.
80 *
81 * - You must notify IRTF-RD regarding your distribution of
82 * the derivative work.
83 *
84 * - You must clearly notify users that your are distributing
85 * a modified version and not the original Harvest software.
86 *
87 * - Any derivative product is also subject to these copyright
88 * and use restrictions.
89 *
90 * Note that the Harvest software is NOT in the public domain. We
91 * retain copyright, as specified above.
92 *
93 * HISTORY OF FREE SOFTWARE STATUS
94 *
95 * Originally we required sites to license the software in cases
96 * where they were going to build commercial products/services
97 * around Harvest. In June 1995 we changed this policy. We now
98 * allow people to use the core Harvest software (the code found in
99 * the Harvest ``src/'' directory) for free. We made this change
100 * in the interest of encouraging the widest possible deployment of
101 * the technology. The Harvest software is really a reference
102 * implementation of a set of protocols and formats, some of which
103 * we intend to standardize. We encourage commercial
104 * re-implementations of code complying to this set of standards.
7528fc90 105 */
44a47c6e 106
107#include "squid.h"
ed43818f 108
090089c4 109#define WAIS_DELETE_GAP (64*1024)
110
30a4f2a8 111typedef struct {
112 int fd;
090089c4 113 StoreEntry *entry;
7111c86a 114 method_t method;
115 char *relayhost;
116 int relayport;
3a1c3e2f 117 char *request_hdr;
f2052513 118 char request[MAX_URL];
30a4f2a8 119} WaisStateData;
120
582b6456 121static PF waisStateFree;
5c5783a2 122static PF waisTimeout;
582b6456 123static PF waisReadReply;
f17936ab 124static CWCB waisSendComplete;
582b6456 125static PF waisSendRequest;
4f92c80c 126static CNCB waisConnectDone;
bfcaf585 127static STABH waisAbort;
090089c4 128
582b6456 129static void
130waisStateFree(int fd, void *data)
ba718c8f 131{
582b6456 132 WaisStateData *waisState = data;
51fa90db 133 if (waisState == NULL)
582b6456 134 return;
30a4f2a8 135 storeUnlockObject(waisState->entry);
bfcaf585 136 storeUnregisterAbort(waisState->entry);
51fa90db 137 xfree(waisState);
ba718c8f 138}
139
090089c4 140/* This will be called when socket lifetime is expired. */
b8d8561b 141static void
5c5783a2 142waisTimeout(int fd, void *data)
090089c4 143{
582b6456 144 WaisStateData *waisState = data;
145 StoreEntry *entry = waisState->entry;
5c5783a2 146 debug(24, 4, "waisTimeout: FD %d: '%s'\n", fd, entry->url);
147 squid_error_entry(entry, ERR_READ_TIMEOUT, NULL);
51fa90db 148 comm_close(fd);
090089c4 149}
150
151
152
090089c4 153/* This will be called when data is ready to be read from fd. Read until
154 * error or connection closed. */
b8d8561b 155static void
582b6456 156waisReadReply(int fd, void *data)
090089c4 157{
582b6456 158 WaisStateData *waisState = data;
95d659f0 159 LOCAL_ARRAY(char, buf, 4096);
582b6456 160 StoreEntry *entry = waisState->entry;
bfcaf585 161 int len;
56fa4cad 162 int clen;
163 int off;
164 int bin;
bfcaf585 165 if (protoAbortFetch(entry)) {
166 squid_error_entry(entry, ERR_CLIENT_ABORT, NULL);
167 comm_close(fd);
168 return;
169 }
56fa4cad 170 if (entry->flag & DELETE_BEHIND && !storeClientWaiting(entry)) {
171 /* we can terminate connection right now */
172 squid_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
173 comm_close(fd);
174 return;
175 }
176 /* check if we want to defer reading */
177 clen = entry->mem_obj->e_current_len;
178 off = storeGetLowestReaderOffset(entry);
179 if ((clen - off) > WAIS_DELETE_GAP) {
56fa4cad 180 IOStats.Wais.reads_deferred++;
181 debug(24, 3, "waisReadReply: Read deferred for Object: %s\n",
182 entry->url);
183 debug(24, 3, " Current Gap: %d bytes\n", clen - off);
184 /* reschedule, so it will automatically reactivated
185 * when Gap is big enough. */
b177367b 186 commSetSelect(fd,
56fa4cad 187 COMM_SELECT_READ,
cd1fb0eb 188 waisReadReply,
189 waisState, 0);
56fa4cad 190 /* don't install read handler while we're above the gap */
56fa4cad 191 if (!BIT_TEST(entry->flag, READ_DEFERRED)) {
5c5783a2 192 commSetTimeout(fd, Config.Timeout.defer, NULL, NULL);
56fa4cad 193 BIT_SET(entry->flag, READ_DEFERRED);
194 }
195 /* dont try reading again for a while */
196 comm_set_stall(fd, Config.stallDelay);
197 return;
198 } else {
199 BIT_RESET(entry->flag, READ_DEFERRED);
090089c4 200 }
201 len = read(fd, buf, 4096);
4f92c80c 202 fd_bytes(fd, len, FD_READ);
56fa4cad 203 debug(24, 5, "waisReadReply: FD %d read len:%d\n", fd, len);
204 if (len > 0) {
5c5783a2 205 commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
fedac7e5 206 IOStats.Wais.reads++;
207 for (clen = len - 1, bin = 0; clen; bin++)
208 clen >>= 1;
209 IOStats.Wais.read_hist[bin]++;
56fa4cad 210 }
ba718c8f 211 if (len < 0) {
881f7a6c 212 debug(50, 1, "waisReadReply: FD %d: read failure: %s.\n", xstrerror());
0a0bf5db 213 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
6fe6313d 214 /* reinstall handlers */
215 /* XXX This may loop forever */
b177367b 216 commSetSelect(fd, COMM_SELECT_READ,
cd1fb0eb 217 waisReadReply, waisState, 0);
090089c4 218 } else {
1c481e00 219 BIT_RESET(entry->flag, ENTRY_CACHABLE);
2daae136 220 storeReleaseRequest(entry);
b8de7ebe 221 squid_error_entry(entry, ERR_READ_ERROR, xstrerror());
51fa90db 222 comm_close(fd);
090089c4 223 }
ba718c8f 224 } else if (len == 0 && entry->mem_obj->e_current_len == 0) {
b8de7ebe 225 squid_error_entry(entry,
ba718c8f 226 ERR_ZERO_SIZE_OBJECT,
227 errno ? xstrerror() : NULL);
51fa90db 228 comm_close(fd);
090089c4 229 } else if (len == 0) {
230 /* Connection closed; retrieval done. */
b8de7ebe 231 entry->expires = squid_curtime;
090089c4 232 storeComplete(entry);
51fa90db 233 comm_close(fd);
090089c4 234 } else {
235 storeAppend(entry, buf, len);
b177367b 236 commSetSelect(fd,
6fe6313d 237 COMM_SELECT_READ,
cd1fb0eb 238 waisReadReply,
239 waisState, 0);
090089c4 240 }
241}
242
243/* This will be called when request write is complete. Schedule read of
244 * reply. */
b8d8561b 245static void
246waisSendComplete(int fd, char *buf, int size, int errflag, void *data)
090089c4 247{
30a4f2a8 248 WaisStateData *waisState = data;
582b6456 249 StoreEntry *entry = waisState->entry;
56fa4cad 250 debug(24, 5, "waisSendComplete: FD %d size: %d errflag: %d\n",
090089c4 251 fd, size, errflag);
252 if (errflag) {
b8de7ebe 253 squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
51fa90db 254 comm_close(fd);
090089c4 255 } else {
256 /* Schedule read reply. */
b177367b 257 commSetSelect(fd,
6fe6313d 258 COMM_SELECT_READ,
cd1fb0eb 259 waisReadReply,
260 waisState, 0);
090089c4 261 }
090089c4 262}
263
264/* This will be called when connect completes. Write request. */
b8d8561b 265static void
582b6456 266waisSendRequest(int fd, void *data)
090089c4 267{
582b6456 268 WaisStateData *waisState = data;
30a4f2a8 269 int len = strlen(waisState->request) + 4;
2285407f 270 char *buf = NULL;
0ee4272b 271 const char *Method = RequestMethodStr[waisState->method];
090089c4 272
56fa4cad 273 debug(24, 5, "waisSendRequest: FD %d\n", fd);
090089c4 274
8e352276 275 if (Method)
276 len += strlen(Method);
3a1c3e2f 277 if (waisState->request_hdr)
278 len += strlen(waisState->request_hdr);
090089c4 279
30a4f2a8 280 buf = xcalloc(1, len + 1);
090089c4 281
3a1c3e2f 282 if (waisState->request_hdr)
30a4f2a8 283 sprintf(buf, "%s %s %s\r\n", Method, waisState->request,
3a1c3e2f 284 waisState->request_hdr);
090089c4 285 else
30a4f2a8 286 sprintf(buf, "%s %s\r\n", Method, waisState->request);
56fa4cad 287 debug(24, 6, "waisSendRequest: buf: %s\n", buf);
30a4f2a8 288 comm_write(fd,
2285407f 289 buf,
290 len,
2285407f 291 waisSendComplete,
9864ee44 292 (void *) waisState,
293 xfree);
1c481e00 294 if (BIT_TEST(waisState->entry->flag, ENTRY_CACHABLE))
30a4f2a8 295 storeSetPublicKey(waisState->entry); /* Make it public */
296}
297
770f051d 298void
f182d1c5 299waisStart(request_t *request, StoreEntry * entry)
090089c4 300{
30a4f2a8 301 WaisStateData *waisState = NULL;
302 int fd;
75e88d56 303 char *url = entry->url;
f182d1c5 304 method_t method = request->method;
30a4f2a8 305 debug(24, 3, "waisStart: \"%s %s\"\n", RequestMethodStr[method], url);
b6f794d6 306 if (!Config.Wais.relayHost) {
7528fc90 307 debug(24, 0, "waisStart: Failed because no relay host defined!\n");
b8de7ebe 308 squid_error_entry(entry, ERR_NO_RELAY, NULL);
770f051d 309 return;
090089c4 310 }
16b204c4 311 fd = comm_open(SOCK_STREAM,
312 0,
313 Config.Addrs.tcp_outgoing,
314 0,
315 COMM_NONBLOCKING,
316 url);
30a4f2a8 317 if (fd == COMM_ERROR) {
7528fc90 318 debug(24, 4, "waisStart: Failed because we're out of sockets.\n");
b8de7ebe 319 squid_error_entry(entry, ERR_NO_FDS, xstrerror());
770f051d 320 return;
090089c4 321 }
30a4f2a8 322 waisState = xcalloc(1, sizeof(WaisStateData));
30a4f2a8 323 waisState->method = method;
b6f794d6 324 waisState->relayhost = Config.Wais.relayHost;
325 waisState->relayport = Config.Wais.relayPort;
f182d1c5 326 waisState->request_hdr = request->headers;
30a4f2a8 327 waisState->fd = fd;
0a0bf5db 328 waisState->entry = entry;
d5aa0e3b 329 xstrncpy(waisState->request, url, MAX_URL);
bfcaf585 330 comm_add_close_handler(waisState->fd, waisStateFree, waisState);
331 storeRegisterAbort(entry, waisAbort, waisState);
5c5783a2 332 commSetTimeout(fd, Config.Timeout.read, waisTimeout, waisState);
770f051d 333 storeLockObject(entry);
edeb28fd 334 commConnectStart(waisState->fd,
e924600d 335 waisState->relayhost,
336 waisState->relayport,
337 waisConnectDone,
338 waisState);
e5f6c5c2 339}
340
341static void
342waisConnectDone(int fd, int status, void *data)
343{
344 WaisStateData *waisState = data;
edeb28fd 345 if (status == COMM_ERR_DNS) {
346 squid_error_entry(waisState->entry, ERR_DNS_FAIL, dns_error_message);
347 comm_close(fd);
348 return;
349 } else if (status != COMM_OK) {
e5f6c5c2 350 squid_error_entry(waisState->entry, ERR_CONNECT_FAIL, xstrerror());
351 comm_close(fd);
352 return;
090089c4 353 }
f900607e 354 if (opt_no_ipcache)
e5f6c5c2 355 ipcacheInvalidate(waisState->relayhost);
b177367b 356 commSetSelect(fd,
30a4f2a8 357 COMM_SELECT_WRITE,
cd1fb0eb 358 waisSendRequest,
359 waisState, 0);
090089c4 360}
bfcaf585 361
362static void
363waisAbort(void *data)
364{
365 HttpStateData *waisState = data;
366 debug(24, 1, "waisAbort: %s\n", waisState->entry->url);
367 comm_close(waisState->fd);
368}