]> git.ipfire.org Git - thirdparty/squid.git/blob - src/wais.cc
Fixed up *Timeout() functions. We might get fooTimeout() called
[thirdparty/squid.git] / src / wais.cc
1
2 /*
3 * $Id: wais.cc,v 1.130 1999/01/20 19:27:12 wessels Exp $
4 *
5 * DEBUG: section 24 WAIS Relay
6 * AUTHOR: Harvest Derived
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
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 the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
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
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36 #include "squid.h"
37
38 typedef struct {
39 int fd;
40 StoreEntry *entry;
41 method_t method;
42 const HttpHeader *request_hdr;
43 char url[MAX_URL];
44 request_t *request;
45 FwdState *fwd;
46 } WaisStateData;
47
48 static PF waisStateFree;
49 static PF waisTimeout;
50 static PF waisReadReply;
51 static CWCB waisSendComplete;
52 static PF waisSendRequest;
53
54 static void
55 waisStateFree(int fdnotused, void *data)
56 {
57 WaisStateData *waisState = data;
58 if (waisState == NULL)
59 return;
60 storeUnlockObject(waisState->entry);
61 requestUnlink(waisState->request);
62 cbdataFree(waisState);
63 }
64
65 /* This will be called when socket lifetime is expired. */
66 static void
67 waisTimeout(int fd, void *data)
68 {
69 WaisStateData *waisState = data;
70 StoreEntry *entry = waisState->entry;
71 debug(24, 4) ("waisTimeout: FD %d: '%s'\n", fd, storeUrl(entry));
72 if (entry->store_status == STORE_PENDING) {
73 if (entry->mem_obj->inmem_hi == 0) {
74 fwdFail(waisState->fwd,
75 errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
76 }
77 }
78 comm_close(fd);
79 }
80
81 /* This will be called when data is ready to be read from fd. Read until
82 * error or connection closed. */
83 static void
84 waisReadReply(int fd, void *data)
85 {
86 WaisStateData *waisState = data;
87 LOCAL_ARRAY(char, buf, 4096);
88 StoreEntry *entry = waisState->entry;
89 int len;
90 int clen;
91 int bin;
92 size_t read_sz;
93 #if DELAY_POOLS
94 delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);
95 #endif
96 if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
97 comm_close(fd);
98 return;
99 }
100 errno = 0;
101 read_sz = 4096;
102 #if DELAY_POOLS
103 read_sz = delayBytesWanted(delay_id, 1, read_sz);
104 #endif
105 Counter.syscalls.sock.reads++;
106 len = read(fd, buf, read_sz);
107 if (len > 0) {
108 fd_bytes(fd, len, FD_READ);
109 #if DELAY_POOLS
110 delayBytesIn(delay_id, len);
111 #endif
112 kb_incr(&Counter.server.all.kbytes_in, len);
113 kb_incr(&Counter.server.other.kbytes_in, len);
114 }
115 debug(24, 5) ("waisReadReply: FD %d read len:%d\n", fd, len);
116 if (len > 0) {
117 commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
118 IOStats.Wais.reads++;
119 for (clen = len - 1, bin = 0; clen; bin++)
120 clen >>= 1;
121 IOStats.Wais.read_hist[bin]++;
122 }
123 if (len < 0) {
124 debug(50, 1) ("waisReadReply: FD %d: read failure: %s.\n",
125 fd, xstrerror());
126 if (ignoreErrno(errno)) {
127 /* reinstall handlers */
128 /* XXX This may loop forever */
129 commSetSelect(fd, COMM_SELECT_READ,
130 waisReadReply, waisState, 0);
131 } else {
132 ErrorState *err;
133 EBIT_CLR(entry->flags, ENTRY_CACHABLE);
134 storeReleaseRequest(entry);
135 err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
136 err->xerrno = errno;
137 err->request = requestLink(waisState->request);
138 errorAppendEntry(entry, err);
139 comm_close(fd);
140 }
141 } else if (len == 0 && entry->mem_obj->inmem_hi == 0) {
142 ErrorState *err;
143 err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
144 err->xerrno = errno;
145 err->request = requestLink(waisState->request);
146 errorAppendEntry(entry, err);
147 comm_close(fd);
148 } else if (len == 0) {
149 /* Connection closed; retrieval done. */
150 entry->expires = squid_curtime;
151 fwdComplete(waisState->fwd);
152 comm_close(fd);
153 } else {
154 storeAppend(entry, buf, len);
155 commSetSelect(fd,
156 COMM_SELECT_READ,
157 waisReadReply,
158 waisState, 0);
159 }
160 }
161
162 /* This will be called when request write is complete. Schedule read of
163 * reply. */
164 static void
165 waisSendComplete(int fd, char *bufnotused, size_t size, int errflag, void *data)
166 {
167 WaisStateData *waisState = data;
168 StoreEntry *entry = waisState->entry;
169 debug(24, 5) ("waisSendComplete: FD %d size: %d errflag: %d\n",
170 fd, size, errflag);
171 if (size > 0) {
172 fd_bytes(fd, size, FD_WRITE);
173 kb_incr(&Counter.server.all.kbytes_out, size);
174 kb_incr(&Counter.server.other.kbytes_out, size);
175 }
176 if (errflag == COMM_ERR_CLOSING)
177 return;
178 if (errflag) {
179 ErrorState *err;
180 err = errorCon(ERR_WRITE_ERROR, HTTP_SERVICE_UNAVAILABLE);
181 err->xerrno = errno;
182 err->request = requestLink(waisState->request);
183 errorAppendEntry(entry, err);
184 comm_close(fd);
185 } else {
186 /* Schedule read reply. */
187 commSetSelect(fd,
188 COMM_SELECT_READ,
189 waisReadReply,
190 waisState, 0);
191 commSetDefer(fd, fwdCheckDeferRead, entry);
192 }
193 }
194
195 /* This will be called when connect completes. Write request. */
196 static void
197 waisSendRequest(int fd, void *data)
198 {
199 WaisStateData *waisState = data;
200 MemBuf mb;
201 const char *Method = RequestMethodStr[waisState->method];
202 debug(24, 5) ("waisSendRequest: FD %d\n", fd);
203 memBufDefInit(&mb);
204 memBufPrintf(&mb, "%s %s HTTP/1.0\r\n", Method, waisState->url);
205 if (waisState->request_hdr) {
206 Packer p;
207 packerToMemInit(&p, &mb);
208 httpHeaderPackInto(waisState->request_hdr, &p);
209 packerClean(&p);
210 }
211 memBufPrintf(&mb, "\r\n");
212 debug(24, 6) ("waisSendRequest: buf: %s\n", mb.buf);
213 comm_write_mbuf(fd, mb, waisSendComplete, waisState);
214 if (EBIT_TEST(waisState->entry->flags, ENTRY_CACHABLE))
215 storeSetPublicKey(waisState->entry); /* Make it public */
216 EBIT_CLR(waisState->entry->flags, ENTRY_FWD_HDR_WAIT);
217 }
218
219 void
220 waisStart(FwdState * fwd)
221 {
222 WaisStateData *waisState = NULL;
223 request_t *request = fwd->request;
224 StoreEntry *entry = fwd->entry;
225 int fd = fwd->server_fd;
226 const char *url = storeUrl(entry);
227 method_t method = request->method;
228 debug(24, 3) ("waisStart: \"%s %s\"\n", RequestMethodStr[method], url);
229 Counter.server.all.requests++;
230 Counter.server.other.requests++;
231 waisState = xcalloc(1, sizeof(WaisStateData));
232 cbdataAdd(waisState, cbdataXfree, 0);
233 waisState->method = method;
234 waisState->request_hdr = &request->header;
235 waisState->fd = fd;
236 waisState->entry = entry;
237 xstrncpy(waisState->url, url, MAX_URL);
238 waisState->request = requestLink(request);
239 waisState->fwd = fwd;
240 comm_add_close_handler(waisState->fd, waisStateFree, waisState);
241 storeLockObject(entry);
242 commSetSelect(fd, COMM_SELECT_WRITE, waisSendRequest, waisState, 0);
243 commSetTimeout(fd, Config.Timeout.read, waisTimeout, waisState);
244 }