]> git.ipfire.org Git - thirdparty/squid.git/blame - src/wais.cc
major code cleanup/unification/rewrite
[thirdparty/squid.git] / src / wais.cc
CommitLineData
6eb42cae 1/* $Id: wais.cc,v 1.17 1996/04/04 01:30:54 wessels Exp $ */
7528fc90 2
3/*
4 * DEBUG: Section 24 wais
5 */
44a47c6e 6
7#include "squid.h"
ed43818f 8
090089c4 9#define WAIS_DELETE_GAP (64*1024)
10
11typedef struct _waisdata {
12 StoreEntry *entry;
ed43818f 13 char host[SQUIDHOSTNAMELEN + 1];
090089c4 14 int port;
15 char *type;
16 char *mime_hdr;
17 char type_id;
18 char request[MAX_URL];
19} WAISData;
20
090089c4 21extern char *dns_error_message;
090089c4 22
ba718c8f 23static void waisCloseAndFree(fd, data)
24 int fd;
25 WAISData *data;
26{
27 if (fd > 0)
28 comm_close(fd);
29 xfree(data);
30}
31
32
33static int wais_url_parser(url, host, port, request)
090089c4 34 char *url;
35 char *host;
36 int *port;
37 char *request;
38{
39 strcpy(host, getWaisRelayHost());
40 *port = getWaisRelayPort();
41 strcpy(request, url);
42
43 return 0;
44}
45
46/* This will be called when timeout on read. */
ba718c8f 47static void waisReadReplyTimeout(fd, data)
090089c4 48 int fd;
49 WAISData *data;
50{
51 StoreEntry *entry = NULL;
52
53 entry = data->entry;
7528fc90 54 debug(24, 4, "waisReadReplyTimeout: Timeout on %d\n url: %s\n", fd, entry->url);
34f12fd1 55 cached_error_entry(entry, ERR_READ_TIMEOUT, NULL);
090089c4 56 comm_set_select_handler(fd, COMM_SELECT_READ, 0, 0);
ba718c8f 57 waisCloseAndFree(fd, data);
090089c4 58}
59
60/* This will be called when socket lifetime is expired. */
61void waisLifetimeExpire(fd, data)
62 int fd;
63 WAISData *data;
64{
65 StoreEntry *entry = NULL;
66
67 entry = data->entry;
7528fc90 68 debug(24, 4, "waisLifeTimeExpire: FD %d: <URL:%s>\n", fd, entry->url);
34f12fd1 69 cached_error_entry(entry, ERR_LIFETIME_EXP, NULL);
090089c4 70 comm_set_select_handler(fd, COMM_SELECT_READ | COMM_SELECT_WRITE, 0, 0);
ba718c8f 71 waisCloseAndFree(fd, data);
090089c4 72}
73
74
75
76
77/* This will be called when data is ready to be read from fd. Read until
78 * error or connection closed. */
79void waisReadReply(fd, data)
80 int fd;
81 WAISData *data;
82{
83 static char buf[4096];
84 int len;
85 StoreEntry *entry = NULL;
86
87 entry = data->entry;
88 if (entry->flag & DELETE_BEHIND) {
89 if (storeClientWaiting(entry)) {
90 /* check if we want to defer reading */
22e4fa85 91 if ((entry->mem_obj->e_current_len -
92 entry->mem_obj->e_lowest_offset) > WAIS_DELETE_GAP) {
ba718c8f 93 debug(24, 3, "waisReadReply: Read deferred for Object: %s\n",
94 entry->url);
7528fc90 95 debug(24, 3, " Current Gap: %d bytes\n",
22e4fa85 96 entry->mem_obj->e_current_len -
97 entry->mem_obj->e_lowest_offset);
ba718c8f 98 /* reschedule, so it will automatically reactivated
99 * when Gap is big enough. */
45cd3339 100 comm_set_select_handler(fd,
101 COMM_SELECT_READ,
102 (PF) waisReadReply,
103 (caddr_t) data);
104#ifdef INSTALL_READ_TIMEOUT_ABOVE_GAP
105 comm_set_select_handler_plus_timeout(fd,
106 COMM_SELECT_TIMEOUT,
107 (PF) waisReadReplyTimeout,
108 (caddr_t) data,
109 getReadTimeout());
110#else
111 comm_set_select_handler_plus_timeout(fd,
112 COMM_SELECT_TIMEOUT,
113 (PF) NULL,
114 (caddr_t) NULL,
115 (time_t) 0);
116#endif
ba718c8f 117 /* dont try reading again for a while */
118 comm_set_stall(fd, getStallDelay());
090089c4 119 return;
120 }
121 } else {
122 /* we can terminate connection right now */
34f12fd1 123 cached_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
ba718c8f 124 waisCloseAndFree(fd, data);
090089c4 125 return;
126 }
127 }
128 len = read(fd, buf, 4096);
7528fc90 129 debug(24, 5, "waisReadReply - fd: %d read len:%d\n", fd, len);
090089c4 130
ba718c8f 131 if (len < 0) {
132 debug(24, 1, "waisReadReply: FD %d: read failure: %s.\n", xstrerror());
133 if (errno == EAGAIN || errno == EWOULDBLOCK) {
6fe6313d 134 /* reinstall handlers */
135 /* XXX This may loop forever */
136 comm_set_select_handler(fd, COMM_SELECT_READ,
137 (PF) waisReadReply, (caddr_t) data);
138 comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT,
139 (PF) waisReadReplyTimeout, (caddr_t) data, getReadTimeout());
090089c4 140 } else {
ba718c8f 141 BIT_RESET(entry->flag, CACHABLE);
142 BIT_SET(entry->flag, RELEASE_REQUEST);
34f12fd1 143 cached_error_entry(entry, ERR_READ_ERROR, xstrerror());
ba718c8f 144 waisCloseAndFree(fd, data);
090089c4 145 }
ba718c8f 146 } else if (len == 0 && entry->mem_obj->e_current_len == 0) {
147 cached_error_entry(entry,
148 ERR_ZERO_SIZE_OBJECT,
149 errno ? xstrerror() : NULL);
150 waisCloseAndFree(fd, data);
090089c4 151 } else if (len == 0) {
152 /* Connection closed; retrieval done. */
153 entry->expires = cached_curtime;
154 storeComplete(entry);
ba718c8f 155 waisCloseAndFree(fd, data);
22e4fa85 156 } else if (((entry->mem_obj->e_current_len + len) > getWAISMax()) &&
090089c4 157 !(entry->flag & DELETE_BEHIND)) {
158 /* accept data, but start to delete behind it */
159 storeStartDeleteBehind(entry);
090089c4 160 storeAppend(entry, buf, len);
6fe6313d 161 comm_set_select_handler(fd,
162 COMM_SELECT_READ,
163 (PF) waisReadReply,
164 (caddr_t) data);
165 comm_set_select_handler_plus_timeout(fd,
166 COMM_SELECT_TIMEOUT,
167 (PF) waisReadReplyTimeout,
168 (caddr_t) data,
169 getReadTimeout());
090089c4 170 } else {
171 storeAppend(entry, buf, len);
6fe6313d 172 comm_set_select_handler(fd,
173 COMM_SELECT_READ,
174 (PF) waisReadReply,
175 (caddr_t) data);
176 comm_set_select_handler_plus_timeout(fd,
177 COMM_SELECT_TIMEOUT,
178 (PF) waisReadReplyTimeout,
179 (caddr_t) data,
180 getReadTimeout());
090089c4 181 }
182}
183
184/* This will be called when request write is complete. Schedule read of
185 * reply. */
186void waisSendComplete(fd, buf, size, errflag, data)
187 int fd;
188 char *buf;
189 int size;
190 int errflag;
191 WAISData *data;
192{
193 StoreEntry *entry = NULL;
194 entry = data->entry;
7528fc90 195 debug(24, 5, "waisSendComplete - fd: %d size: %d errflag: %d\n",
090089c4 196 fd, size, errflag);
197 if (errflag) {
b367f261 198 cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
ba718c8f 199 waisCloseAndFree(fd, data);
090089c4 200 } else {
201 /* Schedule read reply. */
6fe6313d 202 comm_set_select_handler(fd,
203 COMM_SELECT_READ,
204 (PF) waisReadReply,
205 (caddr_t) data);
206 comm_set_select_handler_plus_timeout(fd,
207 COMM_SELECT_TIMEOUT,
208 (PF) waisReadReplyTimeout,
209 (caddr_t) data,
210 getReadTimeout());
090089c4 211 }
212 safe_free(buf); /* Allocated by waisSendRequest. */
213}
214
215/* This will be called when connect completes. Write request. */
216void waisSendRequest(fd, data)
217 int fd;
218 WAISData *data;
219{
220#define CR '\015'
221#define LF '\012'
222 int len = strlen(data->request) + 4;
223 char *buf;
224
7528fc90 225 debug(24, 5, "waisSendRequest - fd: %d\n", fd);
090089c4 226
227 if (data->type)
228 len += strlen(data->type);
229 if (data->mime_hdr)
230 len += strlen(data->mime_hdr);
231
232 buf = (char *) xcalloc(1, len + 1);
233
234 if (data->mime_hdr)
235 sprintf(buf, "%s %s %s%c%c", data->type, data->request,
236 data->mime_hdr, CR, LF);
237 else
238 sprintf(buf, "%s %s%c%c", data->type, data->request, CR, LF);
7528fc90 239 debug(24, 6, "waisSendRequest - buf:%s\n", buf);
34f12fd1 240 icpWrite(fd, buf, len, 30, waisSendComplete, (caddr_t) data);
090089c4 241}
242
243int waisStart(unusedfd, url, type, mime_hdr, entry)
244 int unusedfd;
245 char *url;
246 char *type;
247 char *mime_hdr;
248 StoreEntry *entry;
249{
250 /* Create state structure. */
251 int sock, status;
252 WAISData *data = NULL;
253
7528fc90 254 debug(24, 3, "waisStart - url:%s, type:%s\n", url, type);
255 debug(24, 4, " header: %s\n", mime_hdr);
090089c4 256
257 data = (WAISData *) xcalloc(1, sizeof(WAISData));
258 data->entry = entry;
259
260 if (!getWaisRelayHost()) {
7528fc90 261 debug(24, 0, "waisStart: Failed because no relay host defined!\n");
34f12fd1 262 cached_error_entry(entry, ERR_NO_RELAY, NULL);
090089c4 263 safe_free(data);
264 return COMM_ERROR;
265 }
266 /* Parse url. */
267 (void) wais_url_parser(url, data->host, &data->port, data->request);
268 data->type = type;
269 data->mime_hdr = mime_hdr;
270
271 /* Create socket. */
272 sock = comm_open(COMM_NONBLOCKING, 0, 0, url);
273 if (sock == COMM_ERROR) {
7528fc90 274 debug(24, 4, "waisStart: Failed because we're out of sockets.\n");
34f12fd1 275 cached_error_entry(entry, ERR_NO_FDS, xstrerror());
090089c4 276 safe_free(data);
277 return COMM_ERROR;
278 }
279 /* check if IP is already in cache. It must be.
280 * It should be done before this route is called.
281 * Otherwise, we cannot check return code for connect. */
282 if (!ipcache_gethostbyname(data->host)) {
7528fc90 283 debug(24, 4, "waisstart: Called without IP entry in ipcache. OR lookup failed.\n");
b367f261 284 cached_error_entry(entry, ERR_DNS_FAIL, dns_error_message);
ba718c8f 285 waisCloseAndFree(sock, data);
090089c4 286 return COMM_ERROR;
287 }
288 /* Open connection. */
289 if ((status = comm_connect(sock, data->host, data->port))) {
290 if (status != EINPROGRESS) {
b367f261 291 cached_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
ba718c8f 292 waisCloseAndFree(sock, data);
090089c4 293 return COMM_ERROR;
294 } else {
7528fc90 295 debug(24, 5, "waisStart - conn %d EINPROGRESS\n", sock);
090089c4 296 }
297 }
298 /* Install connection complete handler. */
299 comm_set_select_handler(sock, COMM_SELECT_LIFETIME,
300 (PF) waisLifetimeExpire, (caddr_t) data);
301 comm_set_select_handler(sock, COMM_SELECT_WRITE,
302 (PF) waisSendRequest, (caddr_t) data);
6eb42cae 303 if (!BIT_TEST(entry->flag, ENTRY_PRIVATE))
304 storeSetPublicKey(entry); /* Make it public */
090089c4 305 return COMM_OK;
306}