]>
Commit | Line | Data |
---|---|---|
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 | ||
11 | typedef 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 | 21 | extern char *dns_error_message; |
090089c4 | 22 | |
ba718c8f | 23 | static 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 | ||
33 | static 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 | 47 | static 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. */ | |
61 | void 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. */ | |
79 | void 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. */ | |
186 | void 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. */ | |
216 | void 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 | ||
243 | int 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 | } |