3 * $Id: wais.cc,v 1.130 1999/01/20 19:27:12 wessels Exp $
5 * DEBUG: section 24 WAIS Relay
6 * AUTHOR: Harvest Derived
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
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.
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.
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.
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.
42 const HttpHeader
*request_hdr
;
48 static PF waisStateFree
;
49 static PF waisTimeout
;
50 static PF waisReadReply
;
51 static CWCB waisSendComplete
;
52 static PF waisSendRequest
;
55 waisStateFree(int fdnotused
, void *data
)
57 WaisStateData
*waisState
= data
;
58 if (waisState
== NULL
)
60 storeUnlockObject(waisState
->entry
);
61 requestUnlink(waisState
->request
);
62 cbdataFree(waisState
);
65 /* This will be called when socket lifetime is expired. */
67 waisTimeout(int fd
, void *data
)
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
));
81 /* This will be called when data is ready to be read from fd. Read until
82 * error or connection closed. */
84 waisReadReply(int fd
, void *data
)
86 WaisStateData
*waisState
= data
;
87 LOCAL_ARRAY(char, buf
, 4096);
88 StoreEntry
*entry
= waisState
->entry
;
94 delay_id delay_id
= delayMostBytesAllowed(entry
->mem_obj
);
96 if (EBIT_TEST(entry
->flags
, ENTRY_ABORTED
)) {
103 read_sz
= delayBytesWanted(delay_id
, 1, read_sz
);
105 Counter
.syscalls
.sock
.reads
++;
106 len
= read(fd
, buf
, read_sz
);
108 fd_bytes(fd
, len
, FD_READ
);
110 delayBytesIn(delay_id
, len
);
112 kb_incr(&Counter
.server
.all
.kbytes_in
, len
);
113 kb_incr(&Counter
.server
.other
.kbytes_in
, len
);
115 debug(24, 5) ("waisReadReply: FD %d read len:%d\n", fd
, len
);
117 commSetTimeout(fd
, Config
.Timeout
.read
, NULL
, NULL
);
118 IOStats
.Wais
.reads
++;
119 for (clen
= len
- 1, bin
= 0; clen
; bin
++)
121 IOStats
.Wais
.read_hist
[bin
]++;
124 debug(50, 1) ("waisReadReply: FD %d: read failure: %s.\n",
126 if (ignoreErrno(errno
)) {
127 /* reinstall handlers */
128 /* XXX This may loop forever */
129 commSetSelect(fd
, COMM_SELECT_READ
,
130 waisReadReply
, waisState
, 0);
133 EBIT_CLR(entry
->flags
, ENTRY_CACHABLE
);
134 storeReleaseRequest(entry
);
135 err
= errorCon(ERR_READ_ERROR
, HTTP_INTERNAL_SERVER_ERROR
);
137 err
->request
= requestLink(waisState
->request
);
138 errorAppendEntry(entry
, err
);
141 } else if (len
== 0 && entry
->mem_obj
->inmem_hi
== 0) {
143 err
= errorCon(ERR_ZERO_SIZE_OBJECT
, HTTP_SERVICE_UNAVAILABLE
);
145 err
->request
= requestLink(waisState
->request
);
146 errorAppendEntry(entry
, err
);
148 } else if (len
== 0) {
149 /* Connection closed; retrieval done. */
150 entry
->expires
= squid_curtime
;
151 fwdComplete(waisState
->fwd
);
154 storeAppend(entry
, buf
, len
);
162 /* This will be called when request write is complete. Schedule read of
165 waisSendComplete(int fd
, char *bufnotused
, size_t size
, int errflag
, void *data
)
167 WaisStateData
*waisState
= data
;
168 StoreEntry
*entry
= waisState
->entry
;
169 debug(24, 5) ("waisSendComplete: FD %d size: %d errflag: %d\n",
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
);
176 if (errflag
== COMM_ERR_CLOSING
)
180 err
= errorCon(ERR_WRITE_ERROR
, HTTP_SERVICE_UNAVAILABLE
);
182 err
->request
= requestLink(waisState
->request
);
183 errorAppendEntry(entry
, err
);
186 /* Schedule read reply. */
191 commSetDefer(fd
, fwdCheckDeferRead
, entry
);
195 /* This will be called when connect completes. Write request. */
197 waisSendRequest(int fd
, void *data
)
199 WaisStateData
*waisState
= data
;
201 const char *Method
= RequestMethodStr
[waisState
->method
];
202 debug(24, 5) ("waisSendRequest: FD %d\n", fd
);
204 memBufPrintf(&mb
, "%s %s HTTP/1.0\r\n", Method
, waisState
->url
);
205 if (waisState
->request_hdr
) {
207 packerToMemInit(&p
, &mb
);
208 httpHeaderPackInto(waisState
->request_hdr
, &p
);
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
);
220 waisStart(FwdState
* fwd
)
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
;
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
);