--------------------- PatchSet 6001 Date: 2003/10/29 22:05:30 Author: dwsquid Branch: icap-2_5 Tag: (none) Log: Support for sending HTTP request bodies to the ICAP server for REQMOD. icap_reqmod.c now gets message body data from client_side.c, chunkifies them, and writes them to the ICAP server. icap_reqmod.c reads chunked message bodies from the ICAP server (in the REQMOD reply) and stores them in a MemBuf. Another function is called from http.c to get the body data and send it off to the origin server. Whereas http.c formerly always called clientReadBody() it now uses a function pointer (request_t->body_reader) so that it can call either clientReadBody() or icapReqModPassHttpBody() as necessary. I found it necessary to add a "client_cookie" member to IcapStateData. This is a cbdataLock()ed pointer that the ICAP side can use to tell if the client side is still valid. Without this, there is no way for ICAP to know if the client connection was closed/aborted and it will get an error trying to write to the client-side FD. Members: src/client_side.c:1.47.2.28.2.12->1.47.2.28.2.13 src/http.c:1.17.6.3.6.14->1.17.6.3.6.15 src/icap_common.c:1.1.2.17->1.1.2.18 src/icap_reqmod.c:1.1.2.13->1.1.2.14 src/protos.h:1.41.6.13.2.14->1.41.6.13.2.15 src/structs.h:1.48.2.9.2.15->1.48.2.9.2.16 src/typedefs.h:1.25.6.1.6.4->1.25.6.1.6.5 Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.47.2.28.2.12 retrieving revision 1.47.2.28.2.13 diff -u -r1.47.2.28.2.12 -r1.47.2.28.2.13 --- squid/src/client_side.c 29 Oct 2003 17:40:23 -0000 1.47.2.28.2.12 +++ squid/src/client_side.c 29 Oct 2003 22:05:30 -0000 1.47.2.28.2.13 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.47.2.28.2.12 2003/10/29 17:40:23 dwsquid Exp $ + * $Id: client_side.c,v 1.47.2.28.2.13 2003/10/29 22:05:30 dwsquid Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -3099,6 +3099,8 @@ if (request->content_length > 0) { conn->body.size_left = request->content_length; request->body_connection = conn; + request->body_reader = clientReadBody; + request->body_reader_data = request; /* Is it too large? */ if (clientRequestBodyTooLarge(request->content_length)) { err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE); @@ -3155,8 +3157,9 @@ /* file_read like function, for reading body content */ void -clientReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata) +clientReadBody(void *data, char *buf, size_t size, CBCB * callback, void *cbdata) { + request_t *request = data; ConnStateData *conn = request->body_connection; if (!conn) { debug(33, 5) ("clientReadBody: no body to read, request=%p\n", request); @@ -3845,7 +3848,8 @@ http->request, http->conn->fd, http->start, - http->conn->log_addr); + http->conn->log_addr, + (void *) http->conn); if (NULL == icap) return 0; return 1; Index: squid/src/http.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/http.c,v retrieving revision 1.17.6.3.6.14 retrieving revision 1.17.6.3.6.15 diff -u -r1.17.6.3.6.14 -r1.17.6.3.6.15 --- squid/src/http.c 29 Oct 2003 16:18:06 -0000 1.17.6.3.6.14 +++ squid/src/http.c 29 Oct 2003 22:05:31 -0000 1.17.6.3.6.15 @@ -1,6 +1,6 @@ /* - * $Id: http.c,v 1.17.6.3.6.14 2003/10/29 16:18:06 dwsquid Exp $ + * $Id: http.c,v 1.17.6.3.6.15 2003/10/29 22:05:31 dwsquid Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -1108,7 +1108,7 @@ debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", httpState->fd, httpState); - if (httpState->orig_request->body_connection) + if (httpState->orig_request->body_reader) sendHeaderDone = httpSendRequestEntry; else sendHeaderDone = httpSendComplete; @@ -1273,7 +1273,9 @@ comm_close(fd); return; } - clientReadBody(httpState->orig_request, memAllocate(MEM_8K_BUF), 8192, httpRequestBodyHandler, httpState); + httpState->orig_request->body_reader( + httpState->orig_request->body_reader_data, + memAllocate(MEM_8K_BUF), 8192, httpRequestBodyHandler, httpState); } void Index: squid/src/icap_common.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/icap_common.c,v retrieving revision 1.1.2.17 retrieving revision 1.1.2.18 diff -u -r1.1.2.17 -r1.1.2.18 --- squid/src/icap_common.c 29 Oct 2003 16:29:58 -0000 1.1.2.17 +++ squid/src/icap_common.c 29 Oct 2003 22:05:31 -0000 1.1.2.18 @@ -1,5 +1,5 @@ /* - * $Id: icap_common.c,v 1.1.2.17 2003/10/29 16:29:58 dwsquid Exp $ + * $Id: icap_common.c,v 1.1.2.18 2003/10/29 22:05:31 dwsquid Exp $ * * DEBUG: section 81 Internet Content Adaptation Protocol (ICAP) Client * AUTHOR: Geetha Manjunath, Hewlett Packard Company @@ -236,8 +236,11 @@ memBufClean(&icap->respmod.resp_copy); if (!memBufIsNull(&icap->reqmod.hdr_buf)) memBufClean(&icap->reqmod.hdr_buf); + if (!memBufIsNull(&icap->reqmod.http_entity.buf)) + memBufClean(&icap->reqmod.http_entity.buf); if (icap->httpState) httpStateFree(-1, icap->httpState); + cbdataUnlock(icap->reqmod.client_cookie); cbdataFree(icap); } Index: squid/src/icap_reqmod.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/icap_reqmod.c,v retrieving revision 1.1.2.13 retrieving revision 1.1.2.14 diff -u -r1.1.2.13 -r1.1.2.14 --- squid/src/icap_reqmod.c 29 Oct 2003 20:31:36 -0000 1.1.2.13 +++ squid/src/icap_reqmod.c 29 Oct 2003 22:05:31 -0000 1.1.2.14 @@ -1,5 +1,5 @@ /* - * $Id: icap_reqmod.c,v 1.1.2.13 2003/10/29 20:31:36 dwsquid Exp $ + * $Id: icap_reqmod.c,v 1.1.2.14 2003/10/29 22:05:31 dwsquid Exp $ * * DEBUG: section 81 Internet Content Adaptation Protocol (ICAP) Client * AUTHOR: Geetha Manjunath, Hewlett Packard Company @@ -45,7 +45,12 @@ int clientHierarchical(clientHttpRequest *); -static PF icapReqModReadHttpPart; +static PF icapReqModReadHttpHdrs; +static PF icapReqModReadHttpBody; +static CWCB icapReqModSendBodyChunk; +static CBCB icapReqModBodyHandler; +static CB icapReqModPassHttpBody; +static STRCB icapReqModMemBufAppend; #define EXPECTED_ICAP_HEADER_LEN 256 static const char *crlf = "\r\n"; @@ -78,6 +83,11 @@ icapReqModCreateClientState(IcapStateData * icap, request_t * request) { clientHttpRequest *http; + if (!cbdataValid(icap->reqmod.client_cookie)) { + debug(81, 1) ("Whups, client cookie invalid\n"); + icap->reqmod.client_fd = -1; + return NULL; + } http = cbdataAlloc(clientHttpRequest); http->uri = xstrdup(urlCanonicalClean(icap->request)); http->log_uri = xstrndup(http->uri, MAX_URL); @@ -107,7 +117,8 @@ icapReqModInterpretHttpRequest(IcapStateData * icap, request_t * request) { clientHttpRequest *http = icapReqModCreateClientState(icap, request); - assert(http); + if (NULL == http) + return; /* * bits from clientReadRequest */ @@ -133,7 +144,10 @@ } /* Do we expect a request-body? */ if (request->content_length > 0) { - fatal("request bodies in ICAP REQMOD not supported yet"); + debug(81, 5) ("handing request bodies in ICAP REQMOD\n"); + request->body_reader = icapReqModPassHttpBody; + request->body_reader_data = icap; /* XXX cbdataLock? */ + memBufDefInit(&icap->reqmod.http_entity.buf); } if (clientCachable(http)) request->flags.cachable = 1; @@ -164,7 +178,8 @@ { ErrorState *err; clientHttpRequest *http = icapReqModCreateClientState(icap, NULL); - assert(http); + if (NULL == http) + return; http->entry = clientCreateStoreEntry(http, icap->request->method, null_request_flags); @@ -254,7 +269,7 @@ hdrlen = inbuf + reqlen - headers; if ((request = urlParse(method, uri)) == NULL) { - debug(81, 3) ("Invalid URL: %s at %s:%d", uri, __FILE__, __LINE__); + debug(81, 3) ("Invalid URL: %s at %s:%d\n", uri, __FILE__, __LINE__); icapEntryError(icap, ERR_INVALID_URL, HTTP_BAD_REQUEST, 0); xfree(inbuf); return; @@ -290,7 +305,8 @@ { extern PF icapReadReply; clientHttpRequest *http = icapReqModCreateClientState(icap, NULL); - assert(http); + if (NULL == http) + return; assert(icap->request); http->entry = clientCreateStoreEntry(http, @@ -306,19 +322,19 @@ } /* - * icapReqModReadHttpPart + * icapReqModReadHttpHdrs * * Read the HTTP reply from the ICAP server. Uses the values * from the ICAP Encapsulation header to know how many bytes * to read. */ static void -icapReqModReadHttpPart(int fd, void *data) +icapReqModReadHttpHdrs(int fd, void *data) { IcapStateData *icap = data; LOCAL_ARRAY(char, tmpbuf, SQUID_TCP_SO_RCVBUF); int rl; - debug(81, 3) ("icapReqModReadHttpPart:\n"); + debug(81, 3) ("icapReqModReadHttpHdrs:\n"); assert(fd == icap->icap_fd); assert(icap->enc.req_hdr == 0); if (0 == icap->reqmod.hdr_state) { @@ -333,7 +349,7 @@ fatalf("unexpected condition in %s:%d", __FILE__, __LINE__); } rl = read(fd, tmpbuf, needed); - debug(81, 3) ("icapReqModReadHttpPart: read %d bytes\n", rl); + debug(81, 3) ("icapReqModReadHttpHdrs: read %d bytes\n", rl); if (rl < 0) { fatalf("need to handle read error at %s:%d", __FILE__, __LINE__); } @@ -341,16 +357,23 @@ icap->http_header_bytes_read_so_far += rl; if (rl != needed) { /* still more header data to read */ - commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpPart, icap, 0); + commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpHdrs, icap, 0); return; } icap->reqmod.hdr_state = 1; } assert(1 == icap->reqmod.hdr_state); - debug(81, 3) ("icapReqModReadHttpPart: read the entire request headers\n"); + debug(81, 3) ("icapReqModReadHttpHdrs: read the entire request headers\n"); icapReqModParseHttpRequest(icap); - comm_close(fd); - return; + if (-1 == icap->reqmod.client_fd) { + /* we detected that the original client_side went away */ + comm_close(fd); + } else if (icap->request->body_reader) { + icap->chunk_size = 0; + commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpBody, icap, 0); + } else { + comm_close(fd); + } } @@ -432,7 +455,7 @@ return; } memBufDefInit(&icap->reqmod.hdr_buf); - commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpPart, icap, 0); + commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpHdrs, icap, 0); return; } @@ -490,10 +513,9 @@ Packer p; IcapStateData *icap = data; char *client_addr; - int blen = 0; - void *b = NULL; int icap_fd = icap->icap_fd; icap_service *service; + CWCB *theCallback; debug(81, 5) ("icapSendReqMod FD %d, status %d\n", fd, status); icap->flags.connect_pending = 0; @@ -507,28 +529,13 @@ comm_close(fd); return; } - if (icap->request->method == METHOD_POST) { - /* TODO: - * Data is usually missing. Sending of data has to be postponed until - * it is read. But we have to take care that some ICAP servers may not - * be able to start the ICAP response before the complete request body - * is read. In that case we do not have the request header to send to - * the HTTP server that the HTTP code needs before reading the body - * from the client. - * At least way, it could work that POSTs are sent to the ICAP server - * without body for now. - */ - ConnStateData *conn = icap->request->body_connection; - if (conn) { - blen = conn->body.bufsize; - b = conn->body.buf; - if (!b) - blen = 0; /* make sure this goes together */ - } - } + if (icap->request->content_length > 0) + theCallback = icapReqModSendBodyChunk; + else + theCallback = icapSendReqModDone; + memBufDefInit(&mb); memBufDefInit(&mb_hdr); - memBufPrintf(&mb_hdr, "%s %s HTTP/%d.%d\r\n", RequestMethodStr[icap->request->method], icap->reqmod.uri, @@ -545,7 +552,7 @@ memBufPrintf(&mb, "REQMOD %s ICAP/1.0\r\n", service->uri); memBufPrintf(&mb, "Encapsulated: req-hdr=0"); /* TODO: Change the offset using 'request' if needed */ - if (blen > 0) + if (icap->request->content_length > 0) memBufPrintf(&mb, ", req-body=%d", mb_hdr.size); else memBufPrintf(&mb, ", null-body=%d", mb_hdr.size); @@ -557,16 +564,9 @@ memBufAppend(&mb, mb_hdr.buf, mb_hdr.size); memBufClean(&mb_hdr); - if (blen > 0) { - memBufPrintf(&mb, "%x\r\n", blen); - memBufAppend(&mb, b, blen); - memBufAppend(&mb, crlf, 2); - /* if (httpState->orig_request->content_length > 0 - * Need to check and see if we have to put content length header */ - } memBufAppend(&mb, crlf, 2); debug(81, 5) ("icapSendReqMod: FD %d writing {%s}\n", icap->icap_fd, mb.buf); - comm_write_mbuf(icap_fd, mb, icapSendReqModDone, icap); + comm_write_mbuf(icap_fd, mb, theCallback, icap); } /* @@ -576,7 +576,7 @@ * structure and request a TCP connection to the server. */ IcapStateData * -icapReqModStart(icap_service_t type, const char *uri, request_t * request, int fd, struct timeval start, struct in_addr log_addr) +icapReqModStart(icap_service_t type, const char *uri, request_t * request, int fd, struct timeval start, struct in_addr log_addr, void *cookie) { IcapStateData *icap = NULL; icap_service *service = NULL; @@ -612,6 +612,8 @@ icap->request = requestLink(request); icap->reqmod.hdr_state = 0; icap->reqmod.client_fd = fd; + icap->reqmod.client_cookie = cookie; + cbdataLock(icap->reqmod.client_cookie); if (!icapConnect(icap, icapSendReqMod)) return NULL; @@ -619,3 +621,167 @@ debug(81, 3) ("icapReqModStart: returning %p\n", icap); return icap; } + +/* + * icapReqModSendBodyChunk + * + * A "comm_write" callback. This is called after comm_write() does + * its job to let us know how things went. If there are no errors, + * get another chunk of the body from client_side. + */ +static void +icapReqModSendBodyChunk(int fd, char *bufnotused, size_t size, int errflag, void *data) +{ + IcapStateData *icap = data; + debug(81, 3) ("icapReqModSendBodyChunk: FD %d wrote %d errflag %d.\n", + fd, (int) size, errflag); + if (errflag == COMM_ERR_CLOSING) + return; + if (errflag) { + icapEntryError(icap, ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR, errno); + comm_close(fd); + return; + } + clientReadBody(icap->request, + memAllocate(MEM_8K_BUF), + 8192, + icapReqModBodyHandler, + icap); +} + +/* + * icapReqModBodyHandler + * + * Called after Squid gets a chunk of the request entity from the + * client side. The body is chunkified and passed to comm_write. + * The comm_write callback depends on whether or not this is the + * last chunk. + */ +static void +icapReqModBodyHandler(char *buf, ssize_t size, void *data) +{ + IcapStateData *icap = data; + MemBuf mb; + CWCB *theCallback = icapReqModSendBodyChunk; + if (size < 0) { + debug(81, 1) ("icapReqModBodyHandler: %s\n", xstrerror()); + memFree8K(buf); + return; + } + memBufDefInit(&mb); + debug(81, 3) ("icapReqModBodyHandler: writing chunk size %d\n", size); + memBufPrintf(&mb, "%x\r\n", size); + if (size) + memBufAppend(&mb, buf, size); + else + theCallback = icapSendReqModDone; + memBufAppend(&mb, crlf, 2); + memFree8K(buf); + comm_write_mbuf(icap->icap_fd, mb, theCallback, icap); +} + +/* + * icapReqModReadHttpBody + * + */ +static void +icapReqModReadHttpBody(int fd, void *data) +{ + IcapStateData *icap = data; + LOCAL_ARRAY(char, tmpbuf, SQUID_TCP_SO_RCVBUF); + int len; + debug(81, 3) ("icapReqModReadHttpBody: FD %d called\n", fd); + len = read(fd, tmpbuf, SQUID_TCP_SO_RCVBUF); + debug(81, 3) ("icapReqModReadHttpBody: read returns %d\n", len); + if (len < 0) { + debug(81, 3) ("icapReqModReadHttpBody: FD %d %s\n", + fd, xstrerror()); + if (!ignoreErrno(errno)) + icap->flags.reqmod_http_entity_eof = 1; + } else if (0 == len) { + debug(81, 3) ("icapReqModReadHttpBody: FD %d EOF\n", fd); + icap->flags.reqmod_http_entity_eof = 1; + } else { + icapParseChunkedBody(icap, len, tmpbuf, + icapReqModMemBufAppend, &icap->reqmod.http_entity.buf); + } + if (!icap->flags.reqmod_http_entity_eof) + commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpBody, icap, 0); + /* + * Notify the other side if it is waiting for data from us + */ + if (icap->reqmod.http_entity.callback && icap->reqmod.http_entity.buf.size) { + icapReqModPassHttpBody(icap, + icap->reqmod.http_entity.callback_buf, + icap->reqmod.http_entity.callback_bufsize, + icap->reqmod.http_entity.callback, + icap->reqmod.http_entity.callback_data); + icap->reqmod.http_entity.callback = NULL; + cbdataUnlock(icap->reqmod.http_entity.callback_data); + } +} + +/* + * icapReqModPassHttpBody + * + * Called from http.c after request headers have been sent. + * This function feeds the http.c module chunks of the request + * body that were stored in the http_entity.buf MemBuf. + */ +static void +icapReqModPassHttpBody(void *data, char *buf, size_t size, CBCB * callback, void *cbdata) +{ + IcapStateData *icap = data; + debug(81, 3) ("icapReqModPassHttpBody: called\n"); + if (!cbdataValid(cbdata)) { + debug(81, 1) ("icapReqModPassHttpBody: FD %d callback data invalid, closing\n", icap->icap_fd); + comm_close(icap->icap_fd); + return; + } + debug(81, 3) ("icapReqModPassHttpBody: entity buf size = %d\n", + icap->reqmod.http_entity.buf.size); + if (icap->reqmod.http_entity.buf.size) { + int copy_sz = icap->reqmod.http_entity.buf.size; + if (copy_sz > size) + copy_sz = size; + xmemcpy(buf, icap->reqmod.http_entity.buf.buf, copy_sz); + /* XXX don't let Alex see this ugliness */ + xmemmove(icap->reqmod.http_entity.buf.buf, + icap->reqmod.http_entity.buf.buf + copy_sz, + icap->reqmod.http_entity.buf.size - copy_sz); + icap->reqmod.http_entity.buf.size -= copy_sz; + debug(81, 3) ("icapReqModPassHttpBody: giving %d bytes to other side\n", + copy_sz); + callback(buf, copy_sz, cbdata); + debug(81, 3) ("icapReqModPassHttpBody: entity buf size now = %d\n", + icap->reqmod.http_entity.buf.size); + return; + } + if (icap->flags.reqmod_http_entity_eof) { + debug(81, 3) ("icapReqModPassHttpBody: signalling EOF\n"); + callback(buf, 0, cbdata); + comm_close(icap->icap_fd); + return; + } + /* + * We have no data for the other side at this point. Save all + * these values and use them when we do have data. + */ + assert(NULL == icap->reqmod.http_entity.callback); + icap->reqmod.http_entity.callback = callback; + icap->reqmod.http_entity.callback_data = cbdata; + icap->reqmod.http_entity.callback_buf = buf; + icap->reqmod.http_entity.callback_bufsize = size; + cbdataLock(icap->reqmod.http_entity.callback_data); +} + +/* + * icapReqModMemBufAppend + * + * stupid wrapper to eliminate compiler warnings + */ +static void +icapReqModMemBufAppend(void *data, const char *buf, ssize_t size) +{ + memBufAppend(data, buf, size); +} Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.41.6.13.2.14 retrieving revision 1.41.6.13.2.15 diff -u -r1.41.6.13.2.14 -r1.41.6.13.2.15 --- squid/src/protos.h 29 Oct 2003 17:40:25 -0000 1.41.6.13.2.14 +++ squid/src/protos.h 29 Oct 2003 22:05:31 -0000 1.41.6.13.2.15 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.41.6.13.2.14 2003/10/29 17:40:25 dwsquid Exp $ + * $Id: protos.h,v 1.41.6.13.2.15 2003/10/29 22:05:31 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -141,7 +141,7 @@ extern void clientHttpConnectionsClose(void); extern StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags); extern int isTcpHit(log_type); -extern void clientReadBody(request_t * req, char *buf, size_t size, CBCB * callback, void *data); +extern CB clientReadBody; extern void clientAbortBody(request_t * req); extern int commSetNonBlocking(int fd); @@ -1366,7 +1366,7 @@ int icapFindHeader(const char *, const char *, const char **, const char **); int icapParseKeepAlive(const IcapStateData *, const char *, const char *); void icapSetKeepAlive(IcapStateData * icap, const char *hdrs); -void icapParseChunkedBody(IcapStateData *, int, const char *, STRCB *, void *); +void icapParseChunkedBody(IcapStateData *, int, const char *, STRCB *, void *); /* @@ -1378,7 +1378,7 @@ /* * icap_reqmod.c */ -IcapStateData *icapReqModStart(icap_service_t, const char *, request_t *, int, struct timeval, struct in_addr); +IcapStateData *icapReqModStart(icap_service_t, const char *, request_t *, int, struct timeval, struct in_addr, void *); /* icap_opt.c */ void icapOptInit(void); Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.48.2.9.2.15 retrieving revision 1.48.2.9.2.16 diff -u -r1.48.2.9.2.15 -r1.48.2.9.2.16 --- squid/src/structs.h 29 Oct 2003 17:40:26 -0000 1.48.2.9.2.15 +++ squid/src/structs.h 29 Oct 2003 22:05:31 -0000 1.48.2.9.2.16 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.48.2.9.2.15 2003/10/29 17:40:26 dwsquid Exp $ + * $Id: structs.h,v 1.48.2.9.2.16 2003/10/29 22:05:31 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1010,10 +1010,18 @@ struct { const char *uri; /* URI for REQMODs */ int client_fd; - struct timeval start; /* for logging */ + struct timeval start; /* for logging */ struct in_addr log_addr; /* for logging */ int hdr_state; MemBuf hdr_buf; + void *client_cookie; + struct { + MemBuf buf; + CBCB *callback; + void *callback_data; + char *callback_buf; + size_t callback_bufsize; + } http_entity; } reqmod; struct { StoreEntry *entry; @@ -1034,6 +1042,7 @@ unsigned int preview_done:1; unsigned int copy_response:1; unsigned int no_content:1; + unsigned int reqmod_http_entity_eof:1; } flags; }; @@ -1804,6 +1813,8 @@ /* icap_service_list* isl[ICAP_SERVICE_MAX]; */ icap_class *class; #endif + CB *body_reader; + void *body_reader_data; }; struct _cachemgr_passwd { Index: squid/src/typedefs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v retrieving revision 1.25.6.1.6.4 retrieving revision 1.25.6.1.6.5 diff -u -r1.25.6.1.6.4 -r1.25.6.1.6.5 --- squid/src/typedefs.h 27 Jun 2003 01:15:19 -0000 1.25.6.1.6.4 +++ squid/src/typedefs.h 29 Oct 2003 22:05:31 -0000 1.25.6.1.6.5 @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.25.6.1.6.4 2003/06/27 01:15:19 hno Exp $ + * $Id: typedefs.h,v 1.25.6.1.6.5 2003/10/29 22:05:31 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -244,6 +244,7 @@ typedef int READ_HANDLER(int, char *, int); typedef int WRITE_HANDLER(int, const char *, int); typedef void CBCB(char *buf, ssize_t size, void *data); +typedef void CB(void *, char *, size_t, CBCB *, void *); typedef void STIOCB(void *their_data, int errflag, storeIOState *); typedef void STFNCB(void *their_data, int errflag, storeIOState *);